题解:P5500 [LnOI2019] 真正的 OIer 从不女装
Solution
直接看询问。若 \(k=0\),则维护区间最大相同子段即可。
若 \(k=1\),来看看怎么操作。
origin:
.>>!|&>>?
changed:
!<<.|?<<&
不好看?我们转一下:(当然答案不变)
&>>?|.>>!
发现了吗?砍一段相当于两小段换位。那么,只有首尾相同对答案才有贡献,及前缀加后缀。(当然,特判全相等的情况,答案为 \(r-l+1\))
推广开,\(k>1\) 与 \(k=1\) 等价。
举个例子
one way origin:
.>>!|&>>?
first changed:
&>>?|.>>!
&>>?>>.|!
second changed:
!|&>>?>>.
another way origin:
.|!>>&>>?
changed:
!>>&>>?|.
Date Structure
线段树维护
vp |
vs |
pre |
suf |
mx |
len |
|---|---|---|---|---|---|
| 第一个元素 | 最后一个元素 | 前缀最长 | 后缀最长 | 最大相同子段 | 区间长度 |
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
struct node{
int vp,vs;
int pre,suf;
int mx;
int len;
int tag;
node(int l=0):len(l){
vp=vs=0;
pre=suf=0;
mx=tag=0;
return;
}
}tr[N<<2],kong;
int n,m;
int a[N];
void push_up(int p){
tr[p].vp=tr[p<<1].vp;
tr[p].vs=tr[p<<1|1].vs;
tr[p].pre=tr[p<<1].pre;
tr[p].suf=tr[p<<1|1].suf;
if(tr[p].pre==tr[p<<1].len&&tr[p<<1].vs==tr[p<<1|1].vp)
tr[p].pre+=tr[p<<1|1].pre;
if(tr[p].suf==tr[p<<1|1].len&&tr[p<<1].vs==tr[p<<1|1].vp)
tr[p].suf+=tr[p<<1].suf;
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
if(tr[p<<1].vs==tr[p<<1|1].vp)
tr[p].mx=max(tr[p].mx,tr[p<<1].suf+tr[p<<1|1].pre);
return;
}
void push_down(int p){
if(tr[p].tag){
tr[p<<1].vp=tr[p<<1].vs=tr[p<<1].tag=tr[p].tag;
tr[p<<1].mx=tr[p<<1].pre=tr[p<<1].suf=tr[p<<1].len;
tr[p<<1|1].vp=tr[p<<1|1].vs=tr[p<<1|1].tag=tr[p].tag;
tr[p<<1|1].mx=tr[p<<1|1].pre=tr[p<<1|1].suf=tr[p<<1|1].len;
tr[p].tag=0;
}
return;
}
void build(int p,int l,int r){
tr[p].len=r-l+1;
if(l==r){
tr[p].vp=tr[p].vs=a[l];
tr[p].mx=tr[p].pre=tr[p].suf=1;
return;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
push_up(p);
return;
}
void assign(int p,int l,int r,int x,int y,int v){
if(y<l||r<x) return;
if(x<=l&&r<=y){
tr[p].vp=tr[p].vs=v;
tr[p].mx=tr[p].pre=tr[p].suf=tr[p].len;
tr[p].tag=v;
return;
}
int mid=l+r>>1;
push_down(p);
assign(p<<1,l,mid,x,y,v);
assign(p<<1|1,mid+1,r,x,y,v);
push_up(p);
return;
}
node query(int p,int l,int r,int x,int y){
if(y<l||r<x) return node();
if(x<=l&&r<=y) return tr[p];
int mid=l+r>>1;
push_down(p);
node res;
node tmpl=query(p<<1,l,mid,x,y);
node tmpr=query(p<<1|1,mid+1,r,x,y);
// cout<<tmpl.vp<<' '<<tmpl.vs<<' '<<tmpl.pre<<' '<<tmpl.suf<<' '<<tmpl.len<<' '<<tmpl.mx<<' '<<l<<' '<<mid<<'\n';
// cout<<tmpr.vp<<' '<<tmpr.vs<<' '<<tmpr.pre<<' '<<tmpr.suf<<' '<<tmpr.len<<' '<<tmpr.mx<<' '<<mid+1<<' '<<r<<'\n';
if(tmpl.len==0) return tmpr;
if(tmpr.len==0) return tmpl;
res.len=tmpr.len+tmpl.len;
res.pre=tmpl.pre;
res.suf=tmpr.suf;
res.vp=tmpl.vp;
res.vs=tmpr.vs;
if(res.pre==tmpl.len&&tmpl.vs==tmpr.vp)
res.pre+=tmpr.pre;
if(res.suf==tmpr.len&&tmpl.vs==tmpr.vp)
res.suf+=tmpl.suf;
res.mx=max(tmpl.mx,tmpr.mx);
if(tmpl.vs==tmpr.vp)
res.mx=max(res.mx,tmpl.suf+tmpr.pre);
return res;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
while(m--){
char op;
int l,r,k;
cin>>op>>l>>r>>k;
if(op=='R'){
assign(1,1,n,l,r,k);
}
if(op=='Q'){
node t=query(1,1,n,l,r);
int ans=t.mx;
if(k>0&&t.vp==t.vs)
ans=min(r-l+1,max(ans,t.pre+t.suf));
cout<<ans<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号