[NOIP10.5模擬賽]1.a題解--離散化+異或線段樹
阿新 • • 發佈:2018-10-06
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題解--離散化+異或線段樹