zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",k^ys1[x[i]]);
    84         }
    85     }
    86     return 0;
    87 }
    View Code

     

  • 相关阅读:
    ESP8266 A0的使用
    电脑总是被乱装各种软件怎么办?那就设置一个密码吧!
    笔记本光驱位改装固态系统硬盘教程
    任务管理器无法呼出
    Python stomp 介绍与代码
    Power(x,y)
    旋转图像
    字符串相乘
    缺失的正数
    外观数列
  • 原文地址:https://www.cnblogs.com/awipppp/p/5992461.html
Copyright © 2011-2022 走看看