zoukankan      html  css  js  c++  java
  • gym-102307 D. Do Not Try This Problem

    题意

    给定一个长度为(n)的字符串(s),给定(q)个操作,每次操作给定(i,a,k,c),表示将(s_i,s_{i+a},dots,s_{i+ka})赋值为字符(c),输出经过(q)次操作后的字符串(s)

    分析

    分类讨论:

    • (a>sqrt n),直接暴力更新,单次操作时间复杂度为(O(sqrt n)),总时间复杂度为(O(nsqrt n))
    • (ale sqrt n),将字符串(s)复制(sqrt{n})(t_1,t_2,dots,t_{sqrt n})(帮助理解算法流程,并不需要真的复制),对每个(a)所有操作离线,倒序来对(t_a)做每个操作,因为(t_{a,i})的最终状态是由最后一次对它的操作决定的,所以每次操作可以将更新过的位置删除,删除可以用并查集或者set来删,并查集更快,当要删除(t_a)中第(i)个位置时,令(fa[a][i]=fa[a][i+k]),这样我们遍历整个序列的时候就可以沿着并查集的边来跑,对于每个(a)的所有操作的时间复杂度为(O(n)),总时间复杂度为(O(nsqrt n))

    怎么将所有的更新操作整合到字符串(s)上呢,用一个辅助数组(mx),当第(j)次操作对第(i)个位置更新时令(mx[i]=max(mx[i],j))。做完所有操作还原出(s)就可以了。

    Code

    #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;
    }
    
  • 相关阅读:
    《Intel汇编第5版》 汇编逆转字符串
    《Intel汇编第5版》 汇编拷贝字符串
    《Intel汇编第5版》 数组求和
    《Intel汇编第5版》 Mov指令
    CABasicAnimation 几种停止的回调
    模拟器SDK路径
    《Intel汇编第5版》 Intel CPU小端序
    《Intel汇编第5版》 汇编减法程序
    Iphone CPU 架构类型
    越狱开发-创建真正的后台程序(Daemon Process)
  • 原文地址:https://www.cnblogs.com/xyq0220/p/12813117.html
Copyright © 2011-2022 走看看