「雅礼集训 2018-04-02」Problem A

有一个长为 NN 的数列 AA ,有 QQ 个操作:

  • 1  L  R  X1 \ \ L \ \ R \ \ X 对于 LiRL\leq i\leq R ,把 AiA_i 变成 AiXA_i \wedge X
  • 2  L  R  X2 \ \ L \ \ R \ \ X 对于 LiRL\leq i\leq R ,把 AiA_i 变成 AiXA_i \vee X
  • 3  L  R3 \ \ L \ \ RAL,AL+1,,ARA_L,A_{L+1},\cdots ,A_R 中的最大值。

其中 $\wedge $ 为按位与 ,$ \vee $为按位或。

Constraints

N,Q2105N,Q \leq 2\cdot 10^50A<2200 \leq A < 2^{20}

Solution

按位与和按位或操作会把对一些数位执行区间赋值操作,所以如果区间内的数这些数位上的数相同,则可以直接打上标记,否则需要递归访问额外节点。过程中需记录区间内数字的与、或和最大值,以方便判断数位是否相同。

下传标记时先与后或。

复杂度 O(20nlogn)O(20nlogn)(其实主要问题在复杂度分析)。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include<cstdio>
#include<algorithm>
#include<cstring>
#define l(x) x<<1
#define r(x) x<<1|1
#define LL long long
using namespace std;
const int N=2e5+5;
int n,m,op,L,R,v,S=(1<<20)-1;
int vor[N*4],vand[N*4],vmx[N*4],tor[N*4],tand[N*4];
int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void mand(int x,int v)
{
tand[x]&=v;tor[x]&=v;
vand[x]&=v;vor[x]&=v;vmx[x]&=v;
}
void mor(int x,int v)
{
tor[x]|=v;
vand[x]|=v;vor[x]|=v;vmx[x]|=v;
}
void up(int x)
{
vand[x]=vand[l(x)]&vand[r(x)];
vor[x]=vor[l(x)]|vor[r(x)];
vmx[x]=max(vmx[l(x)],vmx[r(x)]);
}
void dn(int x)
{
if(tand[x]!=S)
{
mand(l(x),tand[x]);
mand(r(x),tand[x]);
tand[x]=S;
}
if(tor[x]!=0)
{
mor(l(x),tor[x]);
mor(r(x),tor[x]);
tor[x]=0;
}
}
void build(int x,int l,int r)
{
tand[x]=S;
if(l==r){vor[x]=vand[x]=vmx[x]=read();return;}
int mid=(l+r)>>1;
build(l(x),l,mid);
build(r(x),mid+1,r);
up(x);
}
void modify(int x,int l,int r)
{
if(L<=l&&r<=R)
{
if(op==1&&((v^S)&(vand[x]|(vor[x]^S)))==(v^S)){mand(x,v);return;}
if(op==2&&(v&(vand[x]|(vor[x]^S)))==v){mor(x,v);return;}
}
dn(x);int mid=(l+r)>>1;
if(L<=mid)modify(l(x),l,mid);
if(R>mid)modify(r(x),mid+1,r);
up(x);
}
int query(int x,int l,int r)
{
if(L<=l&&r<=R)return vmx[x];
dn(x);int mid=(l+r)>>1,ans=0;
if(L<=mid)ans=max(ans,query(l(x),l,mid));
if(R>mid)ans=max(ans,query(r(x),mid+1,r));
return ans;
}
int main()
{
n=read();m=read();
build(1,1,n);
while(m--)
{
op=read();L=read();R=read();
if(op==3)printf("%d\n",query(1,1,n));
else v=read(),modify(1,1,n);
}
return 0;
}