【BZOJ3685】【zkw权值线段树】普通van Emde Boas树
因为马上要开始搞树套树了,所以学了一波权值线段树。。。毕竟是会点zkw线段树的,所以zkw线段树大法好!
解题思路:
介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数轴上的一段区间,然后统计这个区间内被覆盖的点的数量(我们认为同一个点可以被覆盖多次)
然后这题你就直接权值线段树(因为0还挺麻烦的,所以我们暴力加个1)暴力搞一波即可,具体参见代码吧,不多赘述了。。。。
#include <stdio.h> #define r register #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++) char BB[1<<15],*S=BB,*TT=BB; inline int in(){ r int x=0;r char c;for (;(c=getchar())<'0'||c>'9';); for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); return x; }bool b[1<<20]; int t[1<<21|1],M,n,q; inline void A(int k,int v){for (k+=M; k; k>>=1)t[k]+=v;} inline int Get_Min(int k){for (;k<=M;k=t[k<<1]?k<<1:k<<1|1);return k-M-1;} inline int Get_Max(int k){for (;k<=M;k=t[k<<1|1]?k<<1|1:k<<1);return k-M-1;} inline int prefix(int v){ for (v+=M;v!=1;v>>=1) if ((v&1)&&t[v^1]) return Get_Max(v^1); return -1; } inline int suffix(int v){ for (v+=M;v!=1;v>>=1) if ((~v&1)&&t[v^1]) return Get_Min(v^1); return -1; } int main(){ for(n=in(),q=in(),M=1; M<=n; M<<=1);while(q--){ r int op=in(),x; if (op==1){if (!b[x=in()+1]) b[x]=1,A(x,1);}else if (op==2){if (b[x=in()+1]) b[x]=0,A(x,-1);}else if (op==3) printf("%d\n",t[1]?Get_Min(1):-1);else if (op==4) printf("%d\n",t[1]?Get_Max(1):-1);else if (op==5) printf("%d\n",prefix(in()+1));else if (op==6) printf("%d\n",suffix(in()+1));else printf("%d\n",(b[x=in()+1]?1:-1)); } }