【CodeVS1690】开关灯
Description
YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N)
Input
第 1 行: 用空格隔开的两个整数N和M
第 2..M+1 行: 每行表示一个操作, 有三个用空格分开的整数: 指令号(0代表按下开关,1代表询问状态), x 和 y
Output
第 1..询问总次数 行:对于每一次询问,输出询问的结果
Sample Input
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4
Sample Output
1
2
2
HINT
一共4盏灯,5个操作,下面是每次操作的状态(X代表关上的,O代表开着的):
XXXX -> OOXX -> OXOO -> 询问1~3 -> OOXX -> 询问1~4
题解
线段树,区间改变状态=区间大小-区间和
#include<iostream> #include<cstdio> #define N 100010 using namespace std; struct tree { int L,R; int lc,rc; int sum,bj; }t[N*4]; int cur,tot; void build(int l,int r) { int cur = ++tot;//..... // int k = cur; t[cur].L=l; t[cur].R=r; if (r!=l+1) { t[cur].lc = tot+1; build(l,(l+r)/2); t[cur].rc = tot+1; // build((l+r)/2,r); // t[cur].sum=t[t[cur].lc].sum+t[t[cur].rc].sum; // } else t[cur].sum=0; // } void updata(int k) { t[t[k].lc].bj+=1; t[t[k].rc].bj+=1; t[t[k].lc].sum = t[t[k].lc].R-t[t[k].lc].L-t[t[k].lc].sum; t[t[k].rc].sum = t[t[k].rc].R-t[t[k].rc].L-t[t[k].rc].sum; t[k].bj = 0; } int query(int k,int ll,int rr) { if (t[k].L>=ll && t[k].R<=rr) return t[k].sum; if (t[k].bj%2 !=0) updata(k); int ans=0; int mid = (t[k].L+t[k].R)/2; if (ll<mid) ans+=query(t[k].lc,ll,rr); if (rr>mid) ans+=query(t[k].rc,ll,rr); return ans; } void change (int k,int ll,int rr) { if (t[k].L>=ll && t[k].R<=rr) { t[k].bj++; t[k].sum = t[k].R-t[k].L-t[k].sum; return ; } if (t[k].bj%2 !=0) updata(k); int mid = (t[k].L+t[k].R)/2; /* if (ll<mid) change(t[k].lc,ll,mid); if (rr>mid) change(t[k].rc,mid,rr); 不能这样写,因为mid 不一定比rr小!! 比如说在[1,10) 中修改[2,3) 就把修改范围扩大了!*/ /* if (ll<mid) change(t[k].lc,ll,(ll+rr)/2); if (rr>mid) change(t[k].rc,(ll+rr)/2,rr); 也不能这样写,比如在[1,20)修改[3,5) 就变成了在[1,10)修改[3,4) */ if (ll<mid) change(t[k].lc,ll,rr); if (rr>mid) change(t[k].rc,ll,rr);//所以还是按模板来吧。。。 t[k].sum = t[t[k].lc].sum + t[t[k].rc].sum; } int main() { int n,m,pd,l,r; scanf("%d%d",&n,&m); build (1,n+1); for (int i=1;i<=m;i++) { scanf("%d",&pd); scanf("%d%d",&l,&r); if (pd) printf("%d\n",query(1,l,r+1)); else change(1,l,r+1); } }