題目描述
YYX家門前的街上有N(2<=N<=100000)盞路燈,在晚上六點之前,這些路燈全是關着的,六點之後,會有M(2<=m<=100000)個人陸續按下開關,這些開關可以改變從第i盞燈到第j盞燈的狀態,現在YYX想知道,從第x盞燈到第y盞燈中有多少是亮着的(1<=i,j,x,y<=N)
輸入描述
第 1 行: 用空格隔開的兩個整數N和M
第 2..M+1 行: 每行表示一個操作, 有三個用空格分開的整數: 指令號(0代表按下開關,1代表詢問狀態), x 和 y
輸出描述
第 1..詢問總次數行:對於每一次詢問,輸出詢問的結果
樣例輸入
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4
樣例輸出
1
2
數據範圍及提示
一共4盞燈,5個操作,下面是每次操作的狀態(X代表關上的,O代表開着的):
XXXX -> OOXX -> OXOO -> 詢問1~3 -> OOXX -> 詢問1~4
題解:線段樹模板題
#include <cstdio>
struct TREE{
int l,r,sum;
bool lazy;
}tree[400005];
int n,m,x,y,z;
using namespace std;
inline int read()
{
int f=1,x=0;
char ch=getchar();
if (ch=='-')
{
f=-1;
ch=getchar();
}
while ((ch<'0')||(ch>'9')) ch=getchar();
while ((ch>='0')&&(ch<='9'))
{
x=x*10+ch-48;
ch=getchar();
}
return f*x;
}
inline void build(int root,int l,int r)
{
tree[root].l=l;tree[root].r=r;
if (l==r) return;
build(root*2,l,(l+r)/2);
build(root*2+1,(l+r)/2+1,r);
}
inline void push_down(int root,int l,int r)
{
if (!tree[root].lazy) return;
int mid=(l+r)/2;
tree[root*2].sum=(mid-l+1)-tree[root*2].sum;
tree[root*2].lazy=!tree[root*2].lazy;
tree[root*2+1].sum=(r-mid)-tree[root*2+1].sum;
tree[root*2+1].lazy=!tree[root*2+1].lazy;
tree[root].lazy=0;
}
inline void change(int root,int l,int r)
{
int ll=tree[root].l,rr=tree[root].r;
int mid=(ll+rr)/2;
if ((l<=ll)&&(rr<=r))
{
tree[root].sum=(rr-ll+1)-tree[root].sum;
tree[root].lazy=!tree[root].lazy;
return;
}
push_down(root,ll,rr);
if (l<=mid) change(root*2,l,r);
if (r>mid) change(root*2+1,l,r);
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
inline int find(int root,int l,int r)
{
int ll=tree[root].l,rr=tree[root].r,s=0;
int mid=(ll+rr)/2;
if ((l<=ll)&&(rr<=r)) return tree[root].sum;
push_down(root,ll,rr);
if (l<=mid) s+=find(root*2,l,r);
if (r>mid) s+=find(root*2+1,l,r);
return s;
}
int main()
{
n=read(),m=read();
build(1,1,n);
for (int i=1;i<=m;i++)
{
x=read(),y=read(),z=read();
if (x==0) change(1,y,z); else
printf("%d\n",find(1,y,z));
}
return 0;
}