CF610E Alphabet Permutations

题面
英文题面
题意:给定一个长度为\(n\)的字符串\(s\),有\(m\)次操作:
1.将区间\([L,R]\)内的字符变为\(ch\)
2.给定长度为\(k\)的字符串排列\(t\),向\(s\)中添加字符,使得\(s\)\(t\)为模式循环,求最少的循环次数。
\(n \leq 2\times 10^5 ,m \leq 2\times 10^4, 1 \leq k \leq 10\)
题解:
考虑两个相邻字符\(i\)\(i+1\),它们对答案会产生1的贡献当且仅当:\(p_{c_i} \geq p_{c_{i+1}}\)
这样的话,我们单次查询只需要统计每个字符之间的贡献即可。
用线段树维护这个东西就好了。
时间复杂度:\(O(nlogn \times k^2)\)
代码:

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
char c[202000];
int tr[808000][10][10],len[808000],laz[808000],lft[808000],rit[808000];
int n,m,s,ans,sit,L,R,W;
#define all 1,1,n
#define lt k<<1,l,mid
#define rt k<<1|1,mid+1,r
I add(int k,int w){
	lft[k]=rit[k]=laz[k]=w;
	F(i,0,9)F(j,0,9)tr[k][i][j]=0;
	tr[k][w][w]=len[k]-1;
}
I push_down(int k){
	add(k<<1,laz[k]);add(k<<1|1,laz[k]);laz[k]=-1;
}
I build(int k,int l,int r){
	laz[k]=-1;
	if(l==r)return len[k]=1,lft[k]=rit[k]=c[l]-'a',void();
	re mid=(l+r)>>1;
	build(lt);build(rt);
	F(i,0,9)F(j,0,9)tr[k][i][j]=tr[k<<1][i][j]+tr[k<<1|1][i][j];
	tr[k][rit[k<<1]][lft[k<<1|1]]++;
	lft[k]=lft[k<<1];rit[k]=rit[k<<1|1];
	len[k]=len[k<<1]+len[k<<1|1];
}
I modi(int k,int l,int r,int x,int y,int w){
	if(x>r||y<l)return;
	if(x<=l&&r<=y)return add(k,w),void();
	if(laz[k]!=-1)push_down(k);
	re mid=(l+r)>>1;
	modi(lt,x,y,w);modi(rt,x,y,w);
	F(i,0,9)F(j,0,9)tr[k][i][j]=tr[k<<1][i][j]+tr[k<<1|1][i][j];
	tr[k][rit[k<<1]][lft[k<<1|1]]++;
	lft[k]=lft[k<<1];rit[k]=rit[k<<1|1];
}
char t[20],v;int b[20];
I calc(){
	ans=n;
	scanf("%s",t+1);
	F(i,1,s)b[i]=t[i]-'a';
	F(i,1,s-1)F(j,i+1,s)ans-=tr[1][b[i]][b[j]];
	printf("%d\n",ans);
}
int main(){
	read(n);read(m);read(s);
	scanf("%s",c+1);build(all);
	while(m--){
		read(sit);
		if(sit==1){
			read(L);read(R);scanf("%c",&v);W=v-'a';
			modi(all,L,R,W);
		}
		else calc();
	}
	return 0;
}
posted @ 2020-07-07 22:47  Purple_wzy  阅读(91)  评论(0编辑  收藏  举报