codeforces706D

题意:给你一个可重集,有添加一个数,删除一个数,和询问一个数与这个集合中的一个元素的异或值最大是多少。所有数小于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\n",maxn);
36         }
37     }
38     return 0;
39 }
View Code

我的

 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\n",k^ys1[x[i]]);
84         }
85     }
86     return 0;
87 }
View Code

 

 

posted @ 2016-10-24 12:34  awipppp  阅读(265)  评论(0编辑  收藏  举报