首页 > 代码库 > CSU 1258 异或运算的线段树

CSU 1258 异或运算的线段树

题目大意:
在给定区间内对每个数的最后一个二进制为1的位将其修改为0,如果数本身已经为0了,就不做改变

输出给定区间的所有数的异或值

 

 1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define N 10005 5 #define L ls,x,mid 6 #define R rs,mid+1,y 7 int sum[N<<2],cnt[N<<2],num[N]; 8  9 void push_up(int o)10 {11     sum[o]=sum[o<<1]^sum[o<<1|1];12     cnt[o]=cnt[o<<1]+cnt[o<<1|1];13 }14 15 void build(int o,int x,int y)16 {17     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;18     cnt[o]=0;19     if(x==y){20         if(!num[x]) cnt[o]=1;21         sum[o]=num[x];22         return;23     }24     build(L);25     build(R);26     push_up(o);27 }28 29 void update(int o,int x,int y,int s,int t)30 {31     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;32     if(cnt[o]==y-x+1) return;33     if(x==y){34         sum[o]^=sum[o]&(-sum[o]);35         if(sum[o]==0) cnt[o]=1;36         return;37     }38     if(mid>=s) update(L,s,t);39     if(mid<t) update(R,s,t);40     push_up(o);41 }42 43 int query(int o,int x,int y,int s,int t)44 {45     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;46     if(cnt[o]==y-x+1){47         return 0;48     }49     int ans=0;50     if(x>=s&&y<=t){51         return sum[o];52     }53     if(mid>=s) ans^=query(L,s,t);54     if(mid<t)  ans^=query(R,s,t);55     return ans;56 }57 58 int main()59 {60     int n,m,a,b,c;61     while(~scanf("%d%d",&n,&m)){62         for(int i=1;i<=n;i++)63             scanf("%d",num+i);64 65         build(1,1,n);66 67         for(int i=0;i<m;i++){68             scanf("%d%d%d",&a,&b,&c);69             if(a==1) update(1,1,n,b,c);70             else{71                 int ans=query(1,1,n,b,c);72                 printf("%d\n",ans);73             }74         }75     }76     return 0;77 }

 

CSU 1258 异或运算的线段树