题目描述
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; }