题解 亿块田

传送门

发现对一个区间做操作会使整个区间中的一些相关位变一样
那么线段树维护,区间不完全相同就暴力递归
维护区间当前最大值
复杂度应该是 \(O(n\log^2 n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, q;
int a[N];

namespace force{
	void solve() {
		for (int i=1,op,l,r,x; i<=q; ++i) {
			op=read();
			if (op==1) {
				l=read(); r=read(); x=read();
				for (int j=l; j<=r; ++j) a[j]&=x;
			}
			else if (op==2) {
				l=read(); r=read(); x=read();
				for (int j=l; j<=r; ++j) a[j]|=x;
			}
			else {
				l=read(); r=read(); x=0;
				for (int j=l; j<=r; ++j) x=max(x, a[j]);
				printf("%d\n", x);
			}
		}
	}
}

// namespace task1{
// 	const int lim=20;
// 	const int mask=(1<<lim)-1;
// 	#define tl(p) tl[p]
// 	#define tr(p) tr[p]
// 	int tl[N<<2], tr[N<<2], val[N<<2], tag1[N<<2], tag2[N<<2], same[N<<2], lg[1<<21];
// 	inline void pushup(int p) {
// 		// cout<<"pushup: "<<p<<endl;
// 		val[p]=max(val[p<<1], val[p<<1|1]);
// 		same[p]=0;
// 		// cout<<"val: "<<val[p<<1]<<' '<<val[p<<1|1]<<endl;
// 		for (int i=0,tem=same[p<<1]&same[p<<1|1]; i<lim; ++i)
// 			if (tem&(1<<i) && !((val[p<<1]^val[p<<1|1])&(1<<i)))
// 				same[p]|=1<<i;
// 	}
// 	inline void spread(int p) {
// 		// cout<<"spread: "<<p<<endl;
// 		if (tag1[p]) {
// 			for (int i=0; i<lim; ++i) if (tag1[p]&(1<<i)) {
// 				assert(same[p<<1]&(1<<i) && same[p<<1|1]&(1<<i));
// 				val[p<<1]&=mask^(1<<i), tag1[p<<1]|=1<<i, tag2[p<<1]&=mask^(1<<i);
// 				val[p<<1|1]&=mask^(1<<i), tag1[p<<1|1]|=1<<i, tag2[p<<1|1]&=mask^(1<<i);
// 			}
// 			tag1[p]=0;
// 		}
// 		if (tag2[p]) {
// 			for (int i=0; i<lim; ++i) if (tag2[p]&(1<<i)) {
// 				assert(same[p<<1]&(1<<i) && same[p<<1|1]&(1<<i));
// 				val[p<<1]|=1<<i, tag2[p<<1]|=1<<i, tag1[p<<1]&=mask^(1<<i);
// 				val[p<<1|1]|=1<<i, tag2[p<<1|1]|=1<<i, tag1[p<<1|1]&=mask^(1<<i);
// 			}
// 			tag2[p]=0;
// 		}
// 	}
// 	void build(int p, int l, int r) {
// 		tl(p)=l; tr(p)=r;
// 		if (l==r) {same[p]=mask; val[p]=a[l]; return ;}
// 		int mid=(l+r)>>1;
// 		build(p<<1, l, mid);
// 		build(p<<1|1, mid+1, r);
// 		pushup(p);
// 	}
// 	void upd1(int p, int l, int r, int dat) { // 将 [l, r] 内所有 dat 为 1 的位设为 0
// 		// cout<<"upd1: "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<bitset<20>(dat)<<endl;
// 		// cout<<"mask: "<<bitset<20>(mask)<<endl;
// 		// cout<<"same: "<<bitset<20>(same[p])<<endl;
// 		// cout<<"val: "<<val[p]<<endl;
// 		if (l<=tl(p)&&r>=tr(p)) {
// 			bool flag=0;
// 			for (int i=0; i<lim; ++i) if (dat&(1<<i) && !(same[p]&(1<<i))) flag=1;
// 			// cout<<"flag: "<<flag<<endl;
// 			if (flag) spread(p), upd1(p<<1, l, r, dat), upd1(p<<1|1, l, r, dat), pushup(p);
// 			for (int i=0; i<lim; ++i) if (dat&(1<<i)) val[p]&=mask^(1<<i), tag1[p]|=1<<i, tag2[p]&=mask^(1<<i);
// 			return ;
// 		}
// 		spread(p);
// 		int mid=(tl(p)+tr(p))>>1;
// 		if (l<=mid) upd1(p<<1, l, r, dat);
// 		if (r>mid) upd1(p<<1|1, l, r, dat);
// 		pushup(p);
// 	}
// 	void upd2(int p, int l, int r, int dat) {
// 		// cout<<"upd2: "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<bitset<20>(dat)<<endl;
// 		if (l<=tl(p)&&r>=tr(p)) {
// 			bool flag=0;
// 			for (int i=0; i<lim; ++i) if (dat&(1<<i) && !(same[p]&(1<<i))) flag=1;
// 			if (flag) spread(p), upd2(p<<1, l, r, dat), upd2(p<<1|1, l, r, dat), pushup(p);
// 			for (int i=0; i<lim; ++i) if (dat&(1<<i)) val[p]|=1<<i, tag2[p]|=1<<i, tag1[p]&=mask^(1<<i);
// 			return ;
// 		}
// 		spread(p);
// 		int mid=(tl(p)+tr(p))>>1;
// 		if (l<=mid) upd2(p<<1, l, r, dat);
// 		if (r>mid) upd2(p<<1|1, l, r, dat);
// 		pushup(p);
// 	}
// 	int query(int p, int l, int r) {
// 		if (l<=tl(p)&&r>=tr(p)) return val[p];
// 		spread(p);
// 		int mid=(tl(p)+tr(p))>>1, ans=0;
// 		if (l<=mid) ans=max(ans, query(p<<1, l, r));
// 		if (r>mid) ans=max(ans, query(p<<1|1, l, r));
// 		return ans;
// 	}
// 	void solve() {
// 		build(1, 1, n);
// 		// for (int i=0; i<lim; ++i) lg[1<<i]=i;
// 		for (int i=1,op,l,r,x; i<=q; ++i) {
// 			op=read();
// 			if (op==1) {
// 				l=read(); r=read(); x=read();
// 				upd1(1, l, r, (~x)&mask);
// 			}
// 			else if (op==2) {
// 				l=read(); r=read(); x=read();
// 				upd2(1, l, r, x);
// 			}
// 			else {
// 				l=read(); r=read();
// 				printf("%d\n", query(1, l, r));
// 			}
// 		}
// 	}
// }

namespace task2{
	const int lim=20;
	const int mask=(1<<lim)-1;
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	int tl[N<<2], tr[N<<2], val[N<<2], tag1[N<<2], tag2[N<<2], same[N<<2], lg[1<<21];
	inline void pushup(int p) {
		// cout<<"pushup: "<<p<<endl;
		val[p]=max(val[p<<1], val[p<<1|1]);
		same[p]=(same[p<<1]&same[p<<1|1])&(~(val[p<<1]^val[p<<1|1]));
		// same[p]=0;
		// // cout<<"val: "<<val[p<<1]<<' '<<val[p<<1|1]<<endl;
		// for (int i,tem=same[p<<1]&same[p<<1|1]; tem; tem-=i) {
		// 	i=tem&-tem;
		// 	if (!((val[p<<1]^val[p<<1|1])&i)) same[p]|=i;
		// }
	}
	inline void spread(int p) {
		// cout<<"spread: "<<p<<endl;
		if (tag1[p]) {
			for (int i; tag1[p]; tag1[p]-=i) {
				// assert(same[p<<1]&(1<<i) && same[p<<1|1]&(1<<i));
				i=tag1[p]&-tag1[p];
				val[p<<1]&=mask^i, tag1[p<<1]|=i, tag2[p<<1]&=mask^i;
				val[p<<1|1]&=mask^i, tag1[p<<1|1]|=i, tag2[p<<1|1]&=mask^i;
			}
		}
		if (tag2[p]) {
			for (int i; tag2[p]; tag2[p]-=i) {
				// assert(same[p<<1]&(1<<i) && same[p<<1|1]&(1<<i));
				i=tag2[p]&-tag2[p];
				val[p<<1]|=i, tag2[p<<1]|=i, tag1[p<<1]&=mask^i;
				val[p<<1|1]|=i, tag2[p<<1|1]|=i, tag1[p<<1|1]&=mask^i;
			}
		}
	}
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) {same[p]=mask; val[p]=a[l]; return ;}
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		pushup(p);
	}
	void upd1(int p, int l, int r, int dat) { // 将 [l, r] 内所有 dat 为 1 的位设为 0
		// cout<<"upd1: "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<bitset<20>(dat)<<endl;
		// cout<<"mask: "<<bitset<20>(mask)<<endl;
		// cout<<"same: "<<bitset<20>(same[p])<<endl;
		// cout<<"val: "<<val[p]<<endl;
		if (l<=tl(p)&&r>=tr(p)) {
			bool flag=0;
			for (int tem=dat,i; tem; tem-=i) {
				i=tem&-tem;
				if (!(same[p]&i)) {flag=1; break;}
			}
			// for (int i=0; i<lim; ++i) if (dat&(1<<i) && !(same[p]&(1<<i))) flag=1;
			// cout<<"flag: "<<flag<<endl;
			if (flag) spread(p), upd1(p<<1, l, r, dat), upd1(p<<1|1, l, r, dat), pushup(p);
			for (int tem=dat,i; tem; tem-=i) {
				i=tem&-tem;
				val[p]&=mask^i, tag1[p]|=i, tag2[p]&=mask^i;
			}
			// for (int i=0; i<lim; ++i) if (dat&(1<<i)) val[p]&=mask^(1<<i), tag1[p]|=1<<i, tag2[p]&=mask^(1<<i);
			return ;
		}
		spread(p);
		int mid=(tl(p)+tr(p))>>1;
		if (l<=mid) upd1(p<<1, l, r, dat);
		if (r>mid) upd1(p<<1|1, l, r, dat);
		pushup(p);
	}
	void upd2(int p, int l, int r, int dat) {
		// cout<<"upd2: "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<bitset<20>(dat)<<endl;
		if (l<=tl(p)&&r>=tr(p)) {
			bool flag=0;
			for (int tem=dat,i; tem; tem-=i) {
				i=tem&-tem;
				if (!(same[p]&i)) {flag=1; break;}
			}
			// for (int i=0; i<lim; ++i) if (dat&(1<<i) && !(same[p]&(1<<i))) flag=1;
			if (flag) spread(p), upd2(p<<1, l, r, dat), upd2(p<<1|1, l, r, dat), pushup(p);
			for (int tem=dat,i; tem; tem-=i) {
				i=tem&-tem;
				val[p]|=i, tag2[p]|=i, tag1[p]&=mask^i;
			}
			// for (int i=0; i<lim; ++i) if (dat&(1<<i)) val[p]|=1<<i, tag2[p]|=1<<i, tag1[p]&=mask^(1<<i);
			return ;
		}
		spread(p);
		int mid=(tl(p)+tr(p))>>1;
		if (l<=mid) upd2(p<<1, l, r, dat);
		if (r>mid) upd2(p<<1|1, l, r, dat);
		pushup(p);
	}
	int query(int p, int l, int r) {
		if (l<=tl(p)&&r>=tr(p)) return val[p];
		spread(p);
		int mid=(tl(p)+tr(p))>>1, ans=0;
		if (l<=mid) ans=max(ans, query(p<<1, l, r));
		if (r>mid) ans=max(ans, query(p<<1|1, l, r));
		return ans;
	}
	void solve() {
		build(1, 1, n);
		for (int i=0; i<lim; ++i) lg[1<<i]=i;
		for (int i=1,op,l,r,x; i<=q; ++i) {
			op=read();
			if (op==1) {
				l=read(); r=read(); x=read();
				upd1(1, l, r, (~x)&mask);
			}
			else if (op==2) {
				l=read(); r=read(); x=read();
				upd2(1, l, r, x);
			}
			else {
				l=read(); r=read();
				printf("%d\n", query(1, l, r));
			}
		}
	}
}

signed main()
{
	freopen("farm.in", "r", stdin);
	freopen("farm.out", "w", stdout);

	n=read(); q=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	// force::solve();
	// task1::solve();
	task2::solve();

	return 0;
}
posted @ 2022-05-31 21:56  Administrator-09  阅读(2)  评论(0编辑  收藏  举报