CF240F TorCoder

题面翻译

给定一个长为\(n\)的由a到z组成的字符串,有\(m\)次操作,每次操作将\([l,r]\)这些位置的字符进行重排,得到字典序最小的回文字符串,如果无法操作就不进行。

\(m\)次操作后的字符串。

\(n,m<=100000\)

样例 #1

样例输入 #1

7 2
aabcbaa
1 3
5 7

样例输出 #1

abacaba

样例 #2

样例输入 #2

3 2
abc
1 2
2 3

样例输出 #2

abc

分析

首先考虑如何判断回文,对于一个字符串,如果字符数量为奇数的总数大于 \(1\),进行操作则不能成为一个回文串。

那么要让回文串的字典序最小,则直接前半部分按照字典序排序来填就好了。

考虑维护 \(26\) 个线段树,每个线段树维护区间一个字母出现的个数。

对于区间修改,如果能变成回文串,则先把区间内的字符先删去,再重新排一遍即可。

最后字符串每个位置单点查询就好了。

#include<bits/stdc++.h>
using namespace std;
inline 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<<1)+(x<<3)+(c&15),c=getchar();
	return x*f;
}
int n,m,tag[30][100005<<2],res[30],sum[30][100005<<2];
char s[100005];
void pushup(int num,int let){sum[let][num]=sum[let][num<<1]+sum[let][num<<1|1];}
void pushdown(int num,int l,int r,int let){
	if(tag[let][num]==-1)return;
	int mid=l+r>>1;
	tag[let][num<<1]=tag[let][num<<1|1]=tag[let][num];
	sum[let][num<<1]=(mid-l+1)*tag[let][num];
	sum[let][num<<1|1]=(r-mid)*tag[let][num];
	tag[let][num]=-1;
}
inline void build(int l,int r,int num,int let){
	tag[let][num]=-1;
	if(l==r){
		sum[let][num]=(s[l]-'a'+1==let);
		return;
	}
	int mid=l+r>>1;
	build(l,mid,num<<1,let),build(mid+1,r,num<<1|1,let);
	pushup(num,let);
}
inline void update(int l,int r,int num,int x,int y,int let,int opt){
	if(x>r||y<l)return;
	if(x<=l&&r<=y){
		tag[let][num]=opt,sum[let][num]=(r-l+1)*opt;
		return;
	}
	pushdown(num,l,r,let);
	int mid=l+r>>1;
	update(l,mid,num<<1,x,y,let,opt),update(mid+1,r,num<<1|1,x,y,let,opt);
	pushup(num,let);
}
inline int query(int l,int r,int num,int x,int y,int let){
	if(x>r||y<l)return 0;
	if(x<=l&&r<=y)return sum[let][num];
	pushdown(num,l,r,let);
	int mid=l+r>>1;
	return query(l,mid,num<<1,x,y,let)+query(mid+1,r,num<<1|1,x,y,let);
}
int main(){
	n=read(),m=read();cin>>s+1;
	for(int i=1;i<=26;i++)build(1,n,1,i);
	for(int i=1;i<=m;i++){
		int x=read(),y=read(),cnt=0,let=0;
		for(int j=1;j<=26;j++){
			res[j]=query(1,n,1,x,y,j);
			cnt+=(res[j]&1),let=(res[j]&1?j:let);
		}
		if(cnt>1)continue;
		for(int j=1;j<=26;j++)update(1,n,1,x,y,j,0);
		if(cnt)--res[let],update(1,n,1,x+y>>1,x+y>>1,let,1);
		for(int j=1;j<=26;j++){
			if(res[j]){
				update(1,n,1,x,x+(res[j]>>1)-1,j,1);
				x+=(res[j]>>1);
				update(1,n,1,y-(res[j]>>1)+1,y,j,1);
				y-=(res[j]>>1);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=26;j++){
			if(query(1,n,1,i,i,j))putchar('a'+j-1);
		}
	}
	return 0;
}
posted @ 2023-06-24 13:55  alex_liu09  阅读(25)  评论(0)    收藏  举报