Submission #1329984

#TimeUsernameProblemLanguageResultExecution timeMemory
1329984KerimGift Exchange (JOI24_ho_t4)C++20
88 / 100
2597 ms147752 KiB
#include <bits/stdc++.h>
using namespace std;

static const int NEG_INF = -1000000000;

// -------- Segment tree: range max, point update (1-indexed positions) --------
struct SegMax {
    int n;
    vector<int> st;
    SegMax(int N=0){ init(N); }
    void init(int N){
        n = 1;
        while(n < N) n <<= 1;
        st.assign(2*n, 0);
    }
    void update(int pos, int val){ // pos: 1-indexed
        int p = (pos-1) + n;
        st[p] = max(st[p], val);
        for(p >>= 1; p; p >>= 1) st[p] = max(st[p<<1], st[p<<1|1]);
    }
    int query(int l, int r){ // inclusive, 1-indexed
        if(l > r) return 0;
        int L = (l-1) + n, R = (r-1) + n;
        int ans = 0;
        while(L <= R){
            if(L & 1) ans = max(ans, st[L++]);
            if(!(R & 1)) ans = max(ans, st[R--]);
            L >>= 1; R >>= 1;
        }
        return ans;
    }
};

// Compute S[i] = max j<i such that interval i intersects interval j
// using the decomposition:
//  (1) B_i < A_j < A_i
//  (2) B_j < A_i < A_j
static vector<int> compute_prev_overlap(const vector<int>& A, const vector<int>& B){
    int N = (int)A.size() - 1;
    int M = 2 * N;

    vector<int> S(N+1, 0);

    // Case (1): query on A_j in (B_i, A_i)
    SegMax seg(M+2);
    for(int i=1;i<=N;i++){
        int l = B[i] + 1;
        int r = A[i] - 1;
        if(l <= r) S[i] = max(S[i], seg.query(l, r));
        seg.update(A[i], i);
    }

    // Case (2): maintain active j such that B_j < x < A_j, query at x = A_i
    vector<vector<int>> add(M+3), rem(M+3), qat(M+3);

    for(int i=1;i<=N;i++){
        // IMPORTANT FIX:
        // Only if there exists an integer x with B_i < x < A_i,
        // i.e. B_i+1 <= A_i-1. Otherwise it must NEVER be active.
        if(B[i] + 1 <= A[i] - 1){
            add[B[i] + 1].push_back(i);
            rem[A[i]].push_back(i);
        }
        qat[A[i]].push_back(i);
    }

    set<int> active;
    for(int x=1;x<=M;x++){
        for(int idx: rem[x]) active.erase(idx);
        for(int idx: add[x]) active.insert(idx);

        for(int i: qat[x]){
            auto it = active.lower_bound(i);
            if(it != active.begin()){
                int cand = *prev(it);
                S[i] = max(S[i], cand);
            }
        }
    }

    return S;
}

// -------- Segment tree for max over starts [1..N] with point assignment --------
struct SegPointMax {
    int n;
    vector<int> st;
    SegPointMax(int N=0){ init(N); }
    void init(int N){
        n = 1;
        while(n < N) n <<= 1;
        st.assign(2*n, NEG_INF);
    }
    void setPoint(int pos, int val){ // 1-indexed
        int p = (pos-1) + n;
        st[p] = val;
        for(p >>= 1; p; p >>= 1) st[p] = max(st[p<<1], st[p<<1|1]);
    }
    int query(int l, int r){ // inclusive
        if(l > r) return NEG_INF;
        int L = (l-1) + n, R = (r-1) + n;
        int ans = NEG_INF;
        while(L <= R){
            if(L & 1) ans = max(ans, st[L++]);
            if(!(R & 1)) ans = max(ans, st[R--]);
            L >>= 1; R >>= 1;
        }
        return ans;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;
    vector<int> A(N+1), B(N+1);
    for(int i=1;i<=N;i++) cin >> A[i];
    for(int i=1;i<=N;i++) cin >> B[i];

    // S: max overlapping index to the left
    vector<int> S = compute_prev_overlap(A, B);

    // T: min overlapping index to the right (compute via reverse)
    vector<int> Ar(N+1), Br(N+1);
    for(int i=1;i<=N;i++){
        Ar[i] = A[N+1-i];
        Br[i] = B[N+1-i];
    }
    vector<int> Sr = compute_prev_overlap(Ar, Br);

    vector<int> T(N+1, N+1);
    for(int i=1;i<=N;i++){
        int ri = N + 1 - i;       // index in reversed array
        int prev = Sr[ri];        // max < ri in reversed that overlaps
        if(prev == 0) T[i] = N + 1;
        else T[i] = N + 1 - prev; // maps to min > i in original
    }

    int Q;
    cin >> Q;
    vector<vector<pair<int,int>>> queriesAtL(N+2);
    vector<string> ans(Q);

    for(int qi=0; qi<Q; qi++){
        int L, R;
        cin >> L >> R;
        queriesAtL[L].push_back({R, qi});
    }

    // Rectangles for "i is isolated inside [L,R]":
    // L in [S[i]+1, i], R in [i, T[i]-1]
    vector<vector<int>> addAt(N+2), remAt(N+3);
    for(int i=1;i<=N;i++){
        int Ls = S[i] + 1;
        int Le = i;
        if(Ls <= Le){
            addAt[Ls].push_back(i);
            if(Le + 1 <= N + 1) remAt[Le + 1].push_back(i);
        }
    }

    // For each start s=i, maintain max end among active intervals [i, T[i]-1]
    vector<priority_queue<int>> pqAdd(N+1), pqDel(N+1);

    auto normalize = [&](int s)->int{
        while(!pqAdd[s].empty() && !pqDel[s].empty() && pqAdd[s].top() == pqDel[s].top()){
            pqAdd[s].pop();
            pqDel[s].pop();
        }
        return pqAdd[s].empty() ? NEG_INF : pqAdd[s].top();
    };

    SegPointMax seg(N);

    for(int L=1; L<=N; L++){
        for(int i: remAt[L]){
            int start = i;
            int end = T[i] - 1;
            pqDel[start].push(end);
            seg.setPoint(start, normalize(start));
        }
        for(int i: addAt[L]){
            int start = i;
            int end = T[i] - 1;
            pqAdd[start].push(end);
            seg.setPoint(start, normalize(start));
        }

        for(auto [R, qi] : queriesAtL[L]){
            int bestEnd = seg.query(1, R);          // max end among starts <= R
            ans[qi] = (bestEnd >= R ? "No" : "Yes"); // covered by some rectangle => No
        }
    }

    for(int i=0;i<Q;i++) cout << ans[i] << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...