题意:给你一个可重集,有添加一个数,删除一个数,和询问一个数与这个集合中的一个元素的异或值最大是多少。所有数小于10^9。操作数小于20万。
题解:
我是按位处理,如果从高到低第i位为0,就去集合中找该位为一的,反之则找为0的,而这些数是连续的。
标答线段树,因为它每一层分下去的节点是固定的。
我没有考虑到这一点,写了个二分+树状数组。
标程(by wuvin)
1 #include<bits/stdc++.h> 2 #define N 200005 3 using namespace std; 4 inline int read(){ 5 int ret=0;char ch=getchar(); 6 while(ch<'0'||ch>'9')ch=getchar(); 7 while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); 8 return ret; 9 } 10 struct xds{ 11 int son[2]; 12 int sz; 13 }a[N*33];int cnt; 14 const int L=0,R=1; 15 void insert(int &k,int p,unsigned int x,int f){ 16 a[++cnt]=a[k];k=cnt;a[k].sz+=f; 17 if(p==0) return; 18 insert(a[k].son[x&(1<<(p-1)) ? 1:0],p-1,x,f); 19 } 20 int maxn=0; 21 void query(int k,int p,unsigned x){ 22 if(p==0||k==0) return;int t=x&(1<<(p-1))? 0:1; 23 if( a[a[k].son[t]].sz>0 ) maxn^=1<<(p-1),query(a[k].son[t],p-1,x); 24 else query(a[k].son[t^1],p-1,x); 25 } 26 int n,rt; 27 int main(){ 28 n=read();insert(rt,31,0,1); 29 for(int i=1;i<=n;i++){ 30 char c=getchar();while(c!='+'&&c!='-'&&c!='?')c=getchar(); 31 if(c=='+') insert(rt,31,read(),1); 32 else if(c=='-') insert(rt,31,read(),-1); 33 else { 34 maxn=0;query(rt,31,read()); 35 printf("%d ",maxn); 36 } 37 } 38 return 0; 39 }
我的
1 #include<bits/stdc++.h> 2 #define maxn 200005 3 using namespace std; 4 int n,m,mid,mac[maxn],ys1[maxn]; 5 int x[maxn],vnt[maxn],tot; 6 long long full[35],mi[36],q; 7 struct sd{ 8 int a,b; 9 bool operator < (sd const &e) const{ 10 return a<e.a;}; 11 }does[maxn]; 12 char h; 13 inline void add(int r,int pos){if(pos<=0) return;for(int i=pos;i<=tot;i+=(-i)&i) vnt[i]+=r;} 14 int query(int pos){ 15 int h=0; 16 for(int i=pos;i>0;i-=i&(-i)) h+=vnt[i]; 17 return h+1; 18 } 19 int find(long long k){ 20 int l=0,r=tot,mid;if(ys1[tot]<k) return tot; 21 while(l<r){ 22 mid=l+r>>1; 23 if(ys1[mid]==k) return mid; 24 if(ys1[mid]<k) l=mid+1; 25 else r=mid; 26 } 27 return l; 28 } 29 int main(){ 30 mi[0]=1;mi[1]=2; 31 for(int i=2;i<=34;i++)mi[i]=mi[i-1]*2; 32 for(int i=1;i<=34;i++){ 33 full[i]=mi[i]-1; 34 } 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++){ 37 getchar(); 38 h=getchar(); 39 switch(h) 40 { 41 case '+': 42 mac[i]=1; 43 break; 44 case '-': 45 mac[i]=2; 46 break; 47 case '?': 48 mac[i]=3; 49 } 50 scanf("%d",&does[i].a);does[i].b=i; 51 } 52 sort(does+1,does+n+1);int pre=0,po1,po2; 53 for(int i=1;i<=n;i++){ 54 if(does[i].a!=pre) tot++; 55 ys1[tot]=does[i].a;pre=does[i].a;x[does[i].b]=tot; 56 }vnt[0]=1; 57 for(int i=1;i<=n;i++){ 58 if(mac[i]==1) add(1,x[i]); 59 if(mac[i]==2) add(-1,x[i]); 60 if(mac[i]==3){ 61 long long k=0,num; 62 for(int j=32;j>=0;j--){ 63 q=k|mi[j];q--;q|=mi[j]; 64 if(query(find(q))==1) break; 65 int s=ys1[x[i]]&mi[j]; 66 if(s>0) { 67 q=k|mi[j];q--; 68 } 69 else{ 70 k|=mi[j];q=k-1;q|=mi[j]; 71 } 72 po1=find(q);if(ys1[po1]>q)po1--; 73 po2=find(k-1);if(ys1[po2]>k-1) po2--; 74 num=query(po1)-query(po2); 75 if(num<=0){ 76 if(s) { 77 if(k==0) break; 78 k=q+1; 79 } 80 else k=k&(full[34]^full[j+1]); 81 } 82 } 83 printf("%I64d ",k^ys1[x[i]]); 84 } 85 } 86 return 0; 87 }