联考20200617 T1「雅礼集训 2018 Day7」A

题目传送门

分析:
这里 与 和 或 两种运算明显可以近似处理,我们先考虑 与 的情况
设目前要 与 的值为\(x\)
如果一个区间的 或和 与上 \(x\)为它本身,那么这次操作在这个区间上就没有用,不用向下处理了
如果一个区间的 或和 与上 \(x\)等于这个区间的 与和 与上 \(x\),那么这次操作对这个区间的最小值不会有影响,打上懒标记
这个操作会至少修改区间上的一位,那么一个区间至多会被修改32次
或 操作用类似的方式维护就好了

复杂度\(O(nlognlogA)\)
(INF开的\(2^{30}\)导致直接爆零,一定要注意!)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>

#define maxn 500005
#define INF 2147483647

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m;
int a[maxn];
int mn[maxn<<2],s1[maxn<<2],s2[maxn<<2],lz1[maxn<<2],lz2[maxn<<2];

inline void pushup(int i)
{
	mn[i]=min(mn[i<<1],mn[i<<1|1]);
	s1[i]=s1[i<<1]&s1[i<<1|1];
	s2[i]=s2[i<<1]|s2[i<<1|1];
}
inline void work1(int i,int num)
{lz1[i]&=num,lz2[i]&=num,mn[i]&=num,s1[i]&=num,s2[i]&=num;}
inline void work2(int i,int num)
{lz1[i]|=num,lz2[i]|=num,mn[i]|=num,s1[i]|=num,s2[i]|=num;}
inline void pushdown(int i)
{
	if(lz1[i]!=INF)
	{
		work1(i<<1,lz1[i]),work1(i<<1|1,lz1[i]);
		lz1[i]=INF;
	}
	if(lz2[i])
	{
		work2(i<<1,lz2[i]),work2(i<<1|1,lz2[i]);
		lz2[i]=0;
	}
}

inline void build(int i,int l,int r)
{
	lz1[i]=INF,lz2[i]=0;
	if(l==r){mn[i]=s1[i]=s2[i]=a[l];return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid),build(i<<1|1,mid+1,r);
	pushup(i);
}
inline void update1(int i,int l,int r,int ql,int qr,int num)
{
	if(r<ql||qr<l)return;
	if((s2[i]&num)==s2[i])return;
	if(ql<=l&&r<=qr&&(s1[i]&num)==(s2[i]&num)){work1(i,num);return;}
	pushdown(i);
	int mid=(l+r)>>1;
	update1(i<<1,l,mid,ql,qr,num),update1(i<<1|1,mid+1,r,ql,qr,num);
	pushup(i);
}
inline void update2(int i,int l,int r,int ql,int qr,int num)
{
	if(r<ql||qr<l)return;
	if((s1[i]|num)==s1[i])return;
	if(ql<=l&&r<=qr&&(s1[i]|num)==(s2[i]|num)){work2(i,num);return;}
	pushdown(i);
	int mid=(l+r)>>1;
	update2(i<<1,l,mid,ql,qr,num),update2(i<<1|1,mid+1,r,ql,qr,num);
	pushup(i);
}
inline int query(int i,int l,int r,int ql,int qr)
{
	if(r<ql||qr<l)return INF;
	if(ql<=l&&r<=qr)return mn[i];
	pushdown(i);
	int mid=(l+r)>>1;
	return min(query(i<<1,l,mid,ql,qr),query(i<<1|1,mid+1,r,ql,qr));
}

int main()
{
	n=getint(),m=getint();
	for(int i=1;i<=n;i++)a[i]=getint();
	build(1,1,n);
	while(m--)
	{
		int op=getint();
		if(op==1)
		{
			int l=getint(),r=getint(),x=getint();
			update1(1,1,n,l,r,x);
		}
		if(op==2)
		{
			int l=getint(),r=getint(),x=getint();
			update2(1,1,n,l,r,x);
		}
		if(op==3)
		{
			int l=getint(),r=getint();
			printf("%d\n",query(1,1,n,l,r));
		}
	}
}

posted @ 2020-06-17 22:15  Izayoi_Doyo  阅读(247)  评论(0编辑  收藏  举报