BZOJ 1230 [Usaco2008 Nov]lites 开关灯:线段树异或

题目链接: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\n",sum);
94         }
95     }
96 }

 

posted @ 2017-10-04 00:30  Leohh  阅读(160)  评论(0编辑  收藏  举报