题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1230
题意:
有n盏灯,一开始全是关着的。
有m次操作(p,a,b)。p为0,则将区间[a,b]内的所有灯反转;p为1,则输出[a,b]中有多少盏灯是亮的。
题解:
线段树区间异或。
与一般线段树有两点不同:
(1)更新lazy时为:lazy ^= 1
(2)更新dat时为:dat = len - dat
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 500005 5 #define INF 10000000 6 7 using namespace std; 8 9 int n,m; 10 int tot; 11 int dat[MAX_N]; 12 int lazy[MAX_N]; 13 int lson[MAX_N]; 14 int rson[MAX_N]; 15 16 void init_segment() 17 { 18 tot=1; 19 memset(dat,0,sizeof(dat)); 20 memset(lazy,0,sizeof(lazy)); 21 memset(lson,-1,sizeof(lson)); 22 memset(rson,-1,sizeof(rson)); 23 } 24 25 void create_kid(int now) 26 { 27 if(lson[now]==-1) lson[now]=tot++; 28 if(rson[now]==-1) rson[now]=tot++; 29 } 30 31 void push_down(int now,int len) 32 { 33 if(lazy[now]) 34 { 35 dat[lson[now]]=len-(len>>1)-dat[lson[now]]; 36 dat[rson[now]]=(len>>1)-dat[rson[now]]; 37 lazy[lson[now]]^=lazy[now]; 38 lazy[rson[now]]^=lazy[now]; 39 lazy[now]=0; 40 } 41 } 42 43 void push_up(int now) 44 { 45 dat[now]=dat[lson[now]]+dat[rson[now]]; 46 } 47 48 void update(int a,int b,int k,int l,int r,int x) 49 { 50 if(a<=l && r<=b) 51 { 52 dat[k]=r-l+1-dat[k]; 53 lazy[k]^=x; 54 return; 55 } 56 if(r<a || b<l) return; 57 create_kid(k); 58 push_down(k,r-l+1); 59 int mid=(l+r)>>1; 60 update(a,b,lson[k],l,mid,x); 61 update(a,b,rson[k],mid+1,r,x); 62 push_up(k); 63 } 64 65 void query(int a,int b,int k,int l,int r,int &sum) 66 { 67 if(a<=l && r<=b) 68 { 69 sum+=dat[k]; 70 return; 71 } 72 if(r<a || b<l) return; 73 create_kid(k); 74 push_down(k,r-l+1); 75 int mid=(l+r)>>1; 76 query(a,b,lson[k],l,mid,sum); 77 query(a,b,rson[k],mid+1,r,sum); 78 } 79 80 int main() 81 { 82 init_segment(); 83 scanf("%d%d",&n,&m); 84 int p,a,b; 85 for(int i=0;i<m;i++) 86 { 87 scanf("%d%d%d",&p,&a,&b); 88 if(p==0) update(a,b,0,1,n,1); 89 else 90 { 91 int sum=0; 92 query(a,b,0,1,n,sum); 93 printf("%d ",sum); 94 } 95 } 96 }