给定一个长度为\(n\)的字符串\(s\),给定\(q\)个操作,每次操作给定\(i,a,k,c\),表示将\(s_i,s_{i+a},\dots,s_{i+ka}\)赋值为字符\(c\),输出经过\(q\)次操作后的字符串\(s\)。
分类讨论:
怎么将所有的更新操作整合到字符串\(s\)上呢,用一个辅助数组\(mx\),当第\(j\)次操作对第\(i\)个位置更新时令\(mx[i]=max(mx[i],j)\)。做完所有操作还原出\(s\)就可以了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int M=sqrt(1e5)+10;
const int inf=1e9;
int n,m,q;
char s[N],c[N];
int mx[N],x[N],a[N],k[N],vis[N];
int f[M][N];
int find(int x,int k){
if(f[x][k]==k) return k;
return f[x][k]=find(x,f[x][k]);
}
int main(){
ios::sync_with_stdio(false);
//freopen("in","r",stdin);
cin>>s+1;
cin>>q;
n=strlen(s+1);
m=sqrt(n);
for(int i=1;i<=m;i++){
for(int j=1;j<=n+1;j++) f[i][j]=j;
}
rep(i,1,q){
cin>>x[i]>>a[i]>>k[i]>>c[i];
}
per(i,q,1){
if(a[i]>m){
for(int j=x[i];j<=x[i]+k[i]*a[i];j+=a[i]){
mx[j]=max(mx[j],i);
}
}else{
for(int j=x[i];j<=x[i]+k[i]*a[i];j=find(a[i],j)){
mx[j]=max(mx[j],i);
f[a[i]][j]=find(a[i],min(j+a[i],n+1));
}
}
}
for(int i=1;i<=n;i++) if(mx[i]) s[i]=c[mx[i]];
cout<<s+1<<endl;
return 0;
}
gym-102307 D. Do Not Try This Problem
原文:https://www.cnblogs.com/xyq0220/p/12813117.html