[codevs] 1699 開關燈

題目描述 Description

    YYX家門前的街上有N(2<=N<=100000)盞路燈,在晚上六點以前,這些路燈全是關着的,六點以後,會有M(2<=m<=100000)我的陸續按下開關,這些開關能夠改變從第i盞燈到第j盞燈的狀態,如今YYX想知道,從第x盞燈到第y盞燈中有多少是亮着的(1<=i,j,x,y<=N)spa

輸入描述 Input Description
第 1 行: 用空格隔開的兩個整數N和M
第 2..M+1 行: 每行表示一個操做, 有三個用空格分開的整數: 指令號(0表明按下開關,1表明詢問狀態), x 和 y 
輸出描述 Output Description

第 1..詢問總次數 行:對於每一次詢問,輸出詢問的結果code

樣例輸入 Sample Input

4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4

blog

樣例輸出 Sample Output
1
2
 
數據範圍及提示 Data Size & Hint

一共4盞燈,5個操做,下面是每次操做的狀態(X表明關上的,O表明開着的):ip

XXXX -> OOXX -> OXOO -> 詢問1~3 -> OOXX -> 詢問1~4io

思路

線段樹;class

代碼實現

 1 #include<cstdio>
 2 const int maxn=1e5+10;
 3 inline int min_(int x,int y){return x<y?x:y;}
 4 inline int max_(int x,int y){return x>y?x:y;}
 5 int n,m;
 6 int t[maxn<<2];
 7 bool f[maxn<<2];
 8 void down(int k,int l,int r){
 9     int mid=l+r>>1,ls=k<<1,rs=ls|1;
10     t[ls]=mid-l+1-t[ls],f[ls]^=1;
11     t[rs]=r-mid-t[rs],f[rs]^=1;
12     f[k]^=1;
13 }
14 void change(int k,int l,int r,int al,int ar){
15     if(l==al&&r==ar){
16         t[k]=r-l+1-t[k];
17         f[k]^=1;
18         return;
19     }
20     if(f[k]) down(k,l,r);
21     int mid=l+r>>1,ls=k<<1,rs=ls|1;
22     if(al<=mid) change(ls,l,mid,al,min_(ar,mid));
23     if(ar>mid) change(rs,mid+1,r,max_(al,mid+1),ar);
24     t[k]=t[ls]+t[rs];
25 }
26 int search(int k,int l,int r,int al,int ar){
27     if(l==al&&r==ar) return t[k];
28     if(f[k]) down(k,l,r);
29     int mid=l+r>>1,ls=k<<1,rs=ls|1,ret=0;
30     if(al<=mid) ret+=search(ls,l,mid,al,min_(ar,mid));
31     if(ar>mid) ret+=search(rs,mid+1,r,max_(al,mid+1),ar);
32     return ret;
33 }
34 int main(){
35     scanf("%d%d",&n,&m);
36     int opt,l,r;
37     while(m--){
38         scanf("%d%d%d",&opt,&l,&r);
39         if(opt==0) change(1,1,n,l,r);
40         if(opt==1) printf("%d\n",search(1,1,n,l,r));
41     }
42     return 0;
43 }
相關文章
相關標籤/搜索