题解 亿块田
发现对一个区间做操作会使整个区间中的一些相关位变一样
那么线段树维护,区间不完全相同就暴力递归
维护区间当前最大值
复杂度应该是 \(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;
}