1. 程式人生 > >[NOIP10.5模擬賽]1.a題解--離散化+異或線段樹

[NOIP10.5模擬賽]1.a題解--離散化+異或線段樹

pla freopen unique ont dig 信心 upd mat pac

題目鏈接:

咕咕咕

https://www.luogu.org/problemnew/show/CF817F

閑扯

在Yali經歷幾天折磨後信心摧殘,T1數據結構裸題考場上連暴力都TM沒打滿

分析

觀察到點值巨大,離散化即可

但是註意到\(1,l+1,r+1\)都是會產生答案的,也需要離散化,同時註意數組大小

然後區間異或線段樹,為了查詢我們記錄一個數組\(sum0[now]\)表示now區間0的個數

同時相應的記錄的一個\(sum1[now]\)表示區間1的個數方便各種操作的轉換

下傳標記時需要註意的就不多說了,也不用註意挺多,還挺好碼的

但是註意數組別開小了!!!我們一條區間最多拓展四個點!

代碼

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define ll long long 
#define ri register int 
using std::min;
using std::max;
using std::swap;
using namespace __gnu_pbds;
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn=400005;//數組一定要開大,線段樹最多是平常的四倍
const int inf=0x7fffffff;
int L,R,dta;
int pos=-1;
struct Segment_Tree{
    int sum1[maxn<<2],sum0[maxn<<2];
    int tag[maxn<<2],set[maxn<<2];
    inline void pushup(int now){
        sum0[now]=sum0[now<<1]+sum0[now<<1|1];
        sum1[now]=sum1[now<<1]+sum1[now<<1|1];
        return ;
    }
    void build(int now,int l,int r){
        set[now]=-1,tag[now]=0;
        if(l==r){
            sum0[now]=1,sum1[now]=0;
            return ;
        }
        int mid=(l+r)>>1;
        build(now<<1,l,mid);
        build(now<<1|1,mid+1,r);
        pushup(now);
    }
    inline void pushdown(int now,int ln,int rn){
        if(tag[now]){
            if(set[now]==-1){
                if(set[now<<1]!=-1)set[now<<1]^=1;
                if(set[now<<1|1]!=-1)set[now<<1|1]^=1;
                //tag[now<<1]^=1,tag[now<<1|1]^=1;
                swap(sum1[now<<1],sum0[now<<1]);
                swap(sum1[now<<1|1],sum0[now<<1|1]);
            }
            tag[now]=0;
        }
        if(set[now]!=-1){
            tag[now<<1]=tag[now<<1|1]=0;
            set[now<<1]=set[now<<1|1]=set[now];
            if(set[now]==1){
                sum1[now<<1]=ln,sum0[now<<1]=0;
                sum1[now<<1|1]=rn,sum0[now<<1|1]=0;
            }
            else{
                sum1[now<<1]=0,sum0[now<<1]=rn;
                sum1[now<<1|1]=0,sum0[now<<1|1]=rn;
            }
            set[now]=-1;
        }
        return ;
    }
    void update_s1(int now,int l,int r){
        if(L<=l&&r<=R){
            set[now]=1;
            tag[now]=0;
            sum0[now]=0,sum1[now]=(r-l+1);
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(now,mid-l+1,r-mid);
        if(L<=mid)update_s1(now<<1,l,mid);
        if(mid<R)update_s1(now<<1|1,mid+1,r);
        pushup(now);
    }
    void update_s0(int now,int l,int r){
        if(L<=l&&r<=R){
            set[now]=0;
            tag[now]=0;
            sum0[now]=(r-l+1),sum1[now]=0;
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(now,mid-l+1,r-mid);
        if(L<=mid)update_s0(now<<1,l,mid);
        if(mid<R)update_s0(now<<1|1,mid+1,r);
        pushup(now);
        return ;
    }
    void update_xor(int now,int l,int r){
        if(L<=l&&r<=R){
            if(set[now]!=-1){
                set[now]^=1;
            }
            else tag[now]^=1;
            swap(sum0[now],sum1[now]);
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(now,mid-l+1,r-mid);
        if(L<=mid)update_xor(now<<1,l,mid);
        if(mid<R)update_xor(now<<1|1,mid+1,r);
        pushup(now);
        return ;
    }
    void query(int now,int l,int r){
        if(sum0[now]==0)return ;
        if(l==r){
            pos=l;
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(now,mid-l+1,r-mid);
        if(sum0[now<<1]!=0)query(now<<1,l,mid);
        if(pos!=-1)return;
        if(sum0[now<<1|1]!=0)query(now<<1|1,mid+1,r);
        pushup(now);
        return ;
    }
}T;
struct OP{
    int ty;ll l,r;
}op[maxn];
int n;
ll f[maxn<<2];int tot=0;
gp_hash_table <ll,int> h;
int main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    read(n);
    f[++tot]=1;
    for(ri i=1;i<=n;i++){
        read(op[i].ty),read(op[i].l),read(op[i].r);
        f[++tot]=op[i].l,f[++tot]=op[i].r;
        f[++tot]=op[i].l+1;
        f[++tot]=op[i].r+1;
    }
    std::sort(f+1,f+1+tot);
    tot=std::unique(f+1,f+1+tot)-(f+1);
    for(ri i=1;i<=tot;i++){
        h[f[i]]=i;
    }
    T.build(1,1,tot);
    //tot=1000;
    for(ri i=1;i<=n;i++){
        L=h[op[i].l],R=h[op[i].r];
        //L=op[i].l,R=op[i].r;
        //printf("%d %d\n",L,R);
        if(op[i].ty==1){
            T.update_s1(1,1,tot);
        }
        if(op[i].ty==2){
            T.update_s0(1,1,tot);
        }
        if(op[i].ty==3){
            T.update_xor(1,1,tot);
        }
        pos=-1;
        T.query(1,1,tot);
        //printf("--%d--\n",pos);
        printf("%lld\n",f[pos]);
    }
    return 0;
}

[NOIP10.5模擬賽]1.a題解--離散化+異或線段樹