P2846 [USACO08NOV]Light Switching G(动态开点写法)

Archie

这叫啥啊,区间异或+区间求和

我用动态开点写的

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int x,y,z;
int lazy[4000001];
int tr[4000001];
int ls[4000001];
int rs[400001];
int ct;
void pushdown(int x,int l,int r){
	if(lazy[x]){
		if(!ls[x]) ls[x]=++ct;
		if(!rs[x]) rs[x]=++ct; 
		lazy[ls[x]]^=1;
		lazy[rs[x]]^=1;
		int mid=(l+r)>>1;
		tr[ls[x]]=(mid-l+1-tr[ls[x]]);
		tr[rs[x]]=(r-mid-tr[rs[x]]);
		lazy[x]^=1;
	}
}
void pushup(int r){
	tr[r]=tr[ls[r]]+tr[rs[r]];
}
void chan(int &root,int L,int R,int l,int r){
	if(!root) root=++ct;
	if(l<=L&&R<=r){
		lazy[root]^=1;
		tr[root]=(R-L+1-tr[root]);
		return ;
	}
	int mid=(L+R)>>1;
	pushdown(root,L,R);
	if(l<=mid) chan(ls[root],L,mid,l,r);
	if(r>mid)  chan(rs[root],mid+1,R,l,r);
	pushup(root);
}
int  query(int root,int L,int R,int l,int r){
	if(!root) return 0;
	if(l<=L&&R<=r){
		return tr[root];
	}
	pushdown(root,L,R);
	int mid=(L+R)>>1;
	ll ans=0;
	if(l<=mid) ans+=query(ls[root],L,mid,l,r);
	if(r>mid) ans+=query(rs[root],mid+1,R,l,r) ;
	return ans;
}
int root=0;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i){
		scanf("%d%d%d",&x,&y,&z);
		if(x==0){
			chan(root,1,n,y,z);
		}else{
			printf("%d\n",query(1,1,n,y,z));
		}
	}
	return 0;
} 
posted @ 2021-07-18 16:31  Simex  阅读(34)  评论(0编辑  收藏  举报