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;
}