题解 P2826 【[USACO08NOV]光开关Light Switching】

斯德哥尔摩

2017-10-14 08:19:00

Solution

看到题目就应该想到了 线段树 了吧。。。(虽说标签中也有。。。) 线段树 应该都会。。。 每个节点存 某一范围内所有1的个数 。 具体看注释吧。。。 附代码: ```cpp #include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1//左孩子 #define RSON rt<<1|1//右孩子 #define DATA(x) a[x].data//节点值 #define SIGN(x) a[x].c//懒惰标记 #define LSIDE(x) a[x].l #define RSIDE(x) a[x].r//左右区间 #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)//区间范围 #define MAXN 100010 using namespace std; int n,m; struct node{ int data,c; int l,r; }a[MAXN<<2];//线段树 数组,切记,一定要开 4 倍空间,不然会炸。。。 inline int read(){//弱弱的读入优化。。。 int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void pushup(int rt){//数值上传 DATA(rt)=DATA(LSON)+DATA(RSON);//每个节点(叶节点除外)的值 = 左孩子的值 + 右孩子旳值 } void pushdown(int rt){//标记下传 if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt)) return; SIGN(LSON)^=SIGN(rt);////处理左孩子。取反,从1变为0 或 从0变为1 DATA(LSON)=WIDTH(LSON)-DATA(LSON);//区间范围 = 区间内0的个数 + 区间内1的个数,移项即可。。。 SIGN(RSON)^=SIGN(rt);//处理右孩子 DATA(RSON)=WIDTH(RSON)-DATA(RSON); SIGN(rt)=0;//标记清空 } void buildtree(int l,int r,int rt){//建树 int mid; LSIDE(rt)=l; RSIDE(rt)=r;//这两句是建树的核心之一 if(l==r){ DATA(rt)=0; return; } mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON);//这是核心之二 pushup(rt); } void update(int l,int r,int rt){//修改 int mid; if(l<=LSIDE(rt)&&RSIDE(rt)<=r){//如果该节点在范围内,则 处理 并 返回 SIGN(rt)^=1; DATA(rt)=WIDTH(rt)-DATA(rt);//已解释过。。。见 标记下传 return; } pushdown(rt);//一定要先下传,再递归 mid=LSIDE(rt)+RSIDE(rt)>>1;//分为 左孩子 与 右孩子,分别处理 if(l<=mid)update(l,r,LSON); if(mid<r)update(l,r,RSON); pushup(rt);//一定要上传 } long long query(int l,int r,int rt){ int mid; long long ans=0; if(l<=LSIDE(rt)&&RSIDE(rt)<=r)//如果该节点在范围内 return DATA(rt);//返回节点值 pushdown(rt);//下传标记 mid=LSIDE(rt)+RSIDE(rt)>>1;//分为 左孩子 与 右孩子,分别求和 if(l<=mid)ans+=query(l,r,LSON); if(mid<r)ans+=query(l,r,RSON); return ans;//不要忘记返回值。。。 } int main(){ int f,x,y; n=read();m=read(); buildtree(1,n,1); while(m--){ f=read();x=read();y=read(); if(f==0)update(x,y,1);//分类 if(f==1)printf("%lld\n",query(x,y,1)); } return 0;//终于结束。。。 } ```