Submission #1276194

#TimeUsernameProblemLanguageResultExecution timeMemory
1276194nanaseyuzukiGlobal Warming (CEOI18_glo)C++20
0 / 100
120 ms4492 KiB
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
const int INF = 1e9;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, x;
    if(!(cin >> n >> x)) return 0;
    vi a(n+1);
    vector<int> comp;
    for(int i = 1; i <= n; ++i){
        cin >> a[i];
        comp.push_back(a[i]);
    }
    sort(comp.begin(), comp.end());
    comp.erase(unique(comp.begin(), comp.end()), comp.end());
    int m = (int)comp.size();

    // forward LIS (prefix) using BIT for prefix-max
    vector<int> bit1(m+5, 0);
    auto add1 = [&](int pos, int val){
        while(pos <= m){
            bit1[pos] = max(bit1[pos], val);
            pos += pos & -pos;
        }
    };
    auto get1 = [&](int pos){
        int res = 0;
        while(pos > 0){
            res = max(res, bit1[pos]);
            pos -= pos & -pos;
        }
        return res;
    };

    vector<int> lis(n+1, 0);
    int res = 0;
    for(int i = 1; i <= n; ++i){
        int it = int(lower_bound(comp.begin(), comp.end(), a[i]) - comp.begin()) + 1;
        lis[i] = get1(it - 1) + 1;
        res = max(res, lis[i]);
        add1(it, lis[i]);
    }

    // prepare BIT reversed for suffix queries: we want range max on [it..m],
    // map pos -> rpos = m - pos + 1 and use prefix-max on rpos
    vector<int> bit2(m+5, 0);
    auto add2 = [&](int pos, int val){
        while(pos <= m){
            bit2[pos] = max(bit2[pos], val);
            pos += pos & -pos;
        }
    };
    auto get2 = [&](int pos){
        int r = 0;
        while(pos > 0){
            r = max(r, bit2[pos]);
            pos -= pos & -pos;
        }
        return r;
    };

    // process from right to left
    for(int i = n; i >= 1; --i){
        // find first value >= a[i] + x  (NOT a[i] - x)
        int need_idx = int(lower_bound(comp.begin(), comp.end(), a[i] + x) - comp.begin()) + 1;
        int cur = 0;
        if(need_idx <= m){
            int rpos = m - need_idx + 1; // map suffix [need_idx..m] to prefix [1..rpos]
            cur = get2(rpos);
        }
        int leftLIS = (i > 1 ? lis[i-1] : 0); // guard for i==1
        res = max(res, leftLIS + cur);

        // now compute best suffix starting at i with values > a[i] (strictly larger)
        // find first value > a[i] => upper_bound
        int pos_gt = int(upper_bound(comp.begin(), comp.end(), a[i]) - comp.begin()) + 1;
        if(pos_gt <= m){
            int rpos_gt = m - pos_gt + 1;
            int bestAfter = get2(rpos_gt); // best starting from value > a[i]
            // update position of a[i] (rank)
            int rank_ai = int(lower_bound(comp.begin(), comp.end(), a[i]) - comp.begin()) + 1;
            int upd_pos = m - rank_ai + 1;
            add2(upd_pos, bestAfter + 1);
        } else {
            // no greater value exists -> update a[i] with 1
            int rank_ai = int(lower_bound(comp.begin(), comp.end(), a[i]) - comp.begin()) + 1;
            int upd_pos = m - rank_ai + 1;
            add2(upd_pos, 1);
        }
    }

    cout << res << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...