제출 #1329982

#제출 시각아이디문제언어결과실행 시간메모리
1329982KerimGift Exchange (JOI24_ho_t4)C++20
8 / 100
323 ms40180 KiB
#include <bits/stdc++.h>
using namespace std;

static const int NEG_INF = -1e9;

// -------- Segment tree for range max on values [1..M] (point update) --------
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 s.t. interval i intersects interval 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: B_i < A_j < 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: B_j < A_i < A_j
    vector<vector<int>> add(M+3), rem(M+3), qat(M+3);
    for(int i=1;i<=N;i++){
        if(B[i]+1 <= M) add[B[i]+1].push_back(i); // active starting at x=B+1
        rem[A[i]].push_back(i);                   // inactive from x=A
        qat[A[i]].push_back(i);                   // query at x=A_i
    }

    std::set<int> active;
    for(int x=1;x<=M;x++){
        // remove first: at x==A, interval is not active (open)
        for(int idx: rem[x]) active.erase(idx);
        // add: at x==B+1, interval becomes active
        for(int idx: add[x]) active.insert(idx);

        // process queries for students with A_i == x
        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){ // pos: 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 queryPrefix(int r){ // max on [1..r]
        if(r<=0) return NEG_INF;
        int l=1;
        return query(l,r);
    }
    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 in original order
    vector<int> S = compute_prev_overlap(A,B);

    // T via reversed order
    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 ip = N+1-i;
        int prev_in_rev = Sr[ip]; // index in reversed array (< ip)
        if(prev_in_rev==0) T[i]=N+1;
        else{
            int j = N+1 - prev_in_rev; // map back
            // j is the minimal index > i that overlaps
            T[i]=j;
        }
    }

    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});
    }

    // Events to add/remove each rectangle i on sweep of L
    vector<vector<int>> addAt(N+2), remAt(N+3);
    for(int i=1;i<=N;i++){
        int Lstart = S[i] + 1;
        int Lend   = i;
        if(Lstart<=Lend){
            addAt[Lstart].push_back(i);
            if(Lend+1<=N+1) remAt[Lend+1].push_back(i);
        }
    }

    // For each start position s=i, maintain multiset of ends using lazy PQs
    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 segStart(N);

    for(int L=1; L<=N; L++){
        // apply removals for rectangles whose L-range ended
        for(int i: remAt[L]){
            int startR = i;
            int endR = T[i]-1;
            pqDel[startR].push(endR);
            int cur = normalize(startR);
            segStart.setPoint(startR, cur);
        }
        // apply additions
        for(int i: addAt[L]){
            int startR = i;
            int endR = T[i]-1;
            pqAdd[startR].push(endR);
            int cur = normalize(startR);
            segStart.setPoint(startR, cur);
        }

        // answer queries with this L
        for(auto [R, qi] : queriesAtL[L]){
            // Is there active interval [s, end] with s <= R and end >= R ?
            int bestEnd = segStart.query(1, R);
            ans[qi] = (bestEnd >= R ? "No" : "Yes");
        }
    }

    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...