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 }

 

你可能感兴趣的:(线段树)