【线段树】线段树

【描述】
请你维护一个线段树
支持一下操作
A x l r 区间 and x
O x l r区间 Or x
X x l r 区间 Xor x
S l r 区间求和
【输入】
一个数T,表示数据组数。 一个数n表示初始序列长,m表示查询。 随后n个整数。接下来m次询问, 如上。
n = 1 e 6 m = 1 e 5 A i < 15 T < = 3 n=1e6,m=1e5,A_i<15,T<=3

【思路】

我们注意到 A i A_i 很小,而位运算每一位独立,所以我们可以维护4棵线段树,分别维护每一位即可。上述操作就变成了区间01取反,区间01覆盖,区间求和。注意lazy标记之间的关系。就是这道题,我把输入看错了,对拍了一个小时都没错,一脸懵逼,果然,有一种错误是对拍发现不了的。
代码:

#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define re register
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
int n,m,a[N],b,c;
inline int red(){
    int data=0;int w=1; char ch=0;
    ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return data*w;
}
struct tree{
	int sum[N<<2|1],cover[N<<2|1],ls[N<<2|1],rs[N<<2|1];
	bool rev[N<<2|1];int id;
	inline int len(const int &p){return rs[p]-ls[p]+1;}
	void pushdown(); 
	void pushup(const int &p){pushdown(p);sum[p]=sum[lc]+sum[rc];}
	void pushcover(const int &p,const int &x)
	{
		if(rev[p])rev[p]=0;
		cover[p]=x;sum[p]=len(p)*x;
	}
	void pushrev(const int &p)
	{	
		if(cover[p]!=-1)cover[p]^=1;
		else rev[p]^=1;
		sum[p]=len(p)-sum[p];
	}
	void pushdown(const int &p){
		if(cover[p]!=-1)pushcover(lc,cover[p]),pushcover(rc,cover[p]),cover[p]=-1;
		if(rev[p])pushrev(lc),pushrev(rc),rev[p]=0;
	}
	void build(int p,int l,int r)
	{
		ls[p]=l,rs[p]=r;rev[p]=0;cover[p]=-1;
		if(l==r)return (void)(sum[p]=(bool)(a[l]&(1<<id)));
		int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);
		pushup(p);
	}
	void cor(int p,const int &ql,const int &qr,const int &x){
		pushdown(p);
		if(ql<=ls[p]&&rs[p]<=qr)return pushcover(p,x);
		int mid=(ls[p]+rs[p])>>1;
		if(ql<=mid)cor(lc,ql,qr,x);
		if(qr>mid)cor(rc,ql,qr,x);
		pushup(p);
	}
	void rvs(int p,const int &ql,const int &qr){
		pushdown(p);
		if(ql<=ls[p]&&rs[p]<=qr)return pushrev(p);
		int mid=(ls[p]+rs[p])>>1;
		if(ql<=mid)rvs(lc,ql,qr);
		if(qr>mid)rvs(rc,ql,qr);
		pushup(p);
	}
	int query(int p,const int &ql,const int &qr){
		pushdown(p);
		if(ql<=ls[p]&&rs[p]<=qr)return sum[p];	
		int mid=(ls[p]+rs[p])>>1;
		int ans=0;
		if(ql<=mid)ans+=query(lc,ql,qr);
		if(qr>mid)ans+=query(rc,ql,qr);
		return ans;
	}
}sgt[4];
int l,r,x,ans;
char s;
int main(){
	int T=red();
	for(int re i=0;i^4;i++)sgt[i].id=i;
	while(T--){
		n=red();m=red();
		for(int re i=1;i<=n;++i)a[i]=red();
		for(int re i=0;i^4;i++)sgt[i].build(1,1,n); 
		while(m--){
			scanf("\n%c",&s);
			if(s!='S')x=red();
			l=red()+1;r=red()+1;
			if(s=='S'){
				ans=0;
				for(int re i=0;i^4;i++)ans+=sgt[i].query(1,l,r)<<i;
				printf("%d\n",ans);
				continue;
			}
			for(int re i=0;i^4;i++){
				if(x&(1<<i)){
					if(s=='O')sgt[i].cor(1,l,r,1);
					if(s=='X')sgt[i].rvs(1,l,r);
				}
				else if(s=='A')sgt[i].cor(1,l,r,0);
			}
		}
	}
}
发布了106 篇原创文章 · 获赞 22 · 访问量 5494

猜你喜欢

转载自blog.csdn.net/weixin_44111457/article/details/102021462