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

 

posted @ 2017-05-16 14:42  Melacau  阅读(596)  评论(0编辑  收藏  举报