COGS2638. 数列操作ψ

COGS2638. 数列操作ψ

【题目描述】

给定一个数列a,你需要支持的操作:区间and,区间or,询问区间最大值

【输入格式】

一行两个整数n,m,表示数列长度和操作个数。

接下来一行有n个整数,第i个数表示ai。

接下来m行,每一行均为以下三种操作中的一种

1 l r val:ai=ai and val(l≤i≤r)

2 l r val:ai=ai or val(l≤i≤r)

3 l r:max{ai}(l≤i≤r)

【输出格式】

对于每一个3操作,输出一行整数表示对应的答案

【样例输入】

8 6
4 0 5 7 2 9 12 8
2 2 5 15
1 3 5 2
3 5 7
1 5 7 12
2 1 6 4
3 2 6

【样例输出】

12
15 

【提示】

对于20%数据,n,m≤3000

另有20%数据,1,2操作中l=r

另有20%数据,3操作中l=r

对于100%数据,1≤n,m≤100000,0≤ai,val≤1e9

保证所有操作中1≤l≤r≤n

题解

区间And操作相当于将区间中所有数的某些位全变成0,区间Or操作相当于将区间中所有数的某些位全变成1。

线段树每个节点维护区间And和以及区间Or和,还要维护一个And标记一个Or标记以及区间最大值。

标记的先后顺序是先And后Or。

区间操作先找到区间,如果区间中所有的数要修改的那些位已经全相同,直接打上标记后返回。否则递归处理子区间。

代码

#include<bits/stdc++.h>
#define MAXN 100010
#define INF 0x7fffffff
#define lc rt<<1
#define rc rt<<1|1
namespace IO{
	char buf[1<<15],*fs,*ft;
	inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline int qr(){
		int x=0,rev=0,ch=gc();
		while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=gc();}
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
		return rev?-x:x;}
}using namespace IO;
using namespace std;
int N,Q,tago[MAXN<<2],taga[MAXN<<2],vo[MAXN<<2],va[MAXN<<2],ma[MAXN<<2],a[MAXN];
inline void Up(int rt){
	vo[rt]=vo[lc]|vo[rc];va[rt]=va[lc]&va[rc];
	ma[rt]=max(ma[lc],ma[rc]);
}
inline void PutAnd(int rt,int x){
	taga[rt]&=x;tago[rt]&=x;
	ma[rt]&=x;vo[rt]&=x;va[rt]&=x;
}
inline void PutOr(int rt,int x){
	tago[rt]|=x;
	ma[rt]|=x;vo[rt]|=x;va[rt]|=x;
}
inline void Down(int rt){
	if(taga[rt]^INF){
		PutAnd(lc,taga[rt]);
		PutAnd(rc,taga[rt]);
		taga[rt]=INF;
	}
	if(tago[rt]){
		PutOr(lc,tago[rt]);
		PutOr(rc,tago[rt]);
		tago[rt]=0;
	}
}
void Build(int l,int r,int rt){
	taga[rt]=INF;
	if(l==r){va[rt]=vo[rt]=ma[rt]=a[l];return;}
	int mid=(l+r)>>1;
	Build(l,mid,lc);Build(mid+1,r,rc);
	Up(rt); 
}
void Modify(int L,int R,int l,int r,int rt,int x,bool flag){
	if(L<=l&&R>=r){
		if(flag){//区间& 
			if(((x^INF)&(va[rt]|(vo[rt]^INF)))==(x^INF)){
				PutAnd(rt,x);
				return;
			}
		}
		else{//区间| 
			if((x&(va[rt]|(vo[rt]^INF)))==x){
				PutOr(rt,x);
				return;
			}
		} 
	}
	Down(rt);
	int mid=l+r>>1;
	if(L<=mid)Modify(L,R,l,mid,lc,x,flag);
	if(R>mid)Modify(L,R,mid+1,r,rc,x,flag);
	Up(rt); 
}
int Query(int L,int R,int l,int r,int rt){
	if(L<=l&&R>=r)return ma[rt];
	int mid=(l+r)>>1,ret=0;
	Down(rt);
	if(L<=mid)ret=Query(L,R,l,mid,lc);
	if(R>mid)ret=max(ret,Query(L,R,mid+1,r,rc));
	return ret; 
}
int op,x,y,z;
int main(){
	freopen("series_wei.in","r",stdin);
	freopen("series_wei.out","w",stdout);
	N=qr();Q=qr();
	for(int i=1;i<=N;i++)a[i]=qr();
	Build(1,N,1);
	while(Q--){
		op=qr();x=qr();y=qr();
		if(op==1)z=qr(),Modify(x,y,1,N,1,z,1);
		else if(op==2)z=qr(),Modify(x,y,1,N,1,z,0);
		else printf("%d
",Query(x,y,1,N,1));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lrj998244353/p/8747120.html