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
",ans);
73             }
74         }
75     }
76     return 0;
77 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/3961847.html