题解: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;
}
posted @ 2026-01-30 10:12  concert_b  阅读(0)  评论(0)    收藏  举报