BZOJ 1230 Usaco2008 Nov 开关灯
【题意概述】
给出一个01序列,初始时序列全为0,每次有修改操作或询问操作,修改操作要求把L~R区间中的0变成1,1变成0,查询操作要求输出L~R区间的1的个数
【题解】
线段树。
每次区间修改把区间的$sum$改为$len-sum$即可。
#include<cstdio> #include<algorithm> #define ls (cur<<1) #define rs (cur<<1|1) #define len(x) (a[x].r-a[x].l+1) #define mid ((a[cur].l+a[cur].r)>>1) using namespace std; const int maxn=400010; int n,m,x,y,z; struct tree{int l,r,sum,c;}a[maxn]; void read(int &k){ k=0; int f=1; char c=getchar(); while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while ('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); k*=f; } void build(int cur,int l,int r){ a[cur].l=l; a[cur].r=r; if (l<r) build(ls,l,mid),build(rs,mid+1,r); } void pushdown(int cur){ if (len(cur)==0||a[cur].c==0) return; a[ls].c=1-a[ls].c; a[ls].sum=len(ls)-a[ls].sum; a[rs].c=1-a[rs].c; a[rs].sum=len(rs)-a[rs].sum; a[cur].c=0; } void update(int cur,int l,int r){ if (l<=a[cur].l&&a[cur].r<=r) a[cur].c=1-a[cur].c,a[cur].sum=len(cur)-a[cur].sum; else{ pushdown(cur); if (l<=mid) update(ls,l,r); if (r>mid) update(rs,l,r); a[cur].sum=a[ls].sum+a[rs].sum; } } int query(int cur,int l,int r){ if (l<=a[cur].l&&a[cur].r<=r) return a[cur].sum; else{ pushdown(cur); int ret=0; if (l<=mid) ret+=query(ls,l,r); if (r>mid) ret+=query(rs,l,r); return ret; } } int main(){ read(n); read(m); build(1,1,n); for (int i=1;i<=m;i++){ read(x); read(y); read(z); if (x==0) update(1,y,z); else printf("%d\n",query(1,y,z)); } return 0; }