Gym - 102307D Do Not Try This Problem

 Do Not Try This Problem Gym - 102307D 

题意:给个长度为len的字符串(len<=1e5),然后q次操作(q<=1e5),每次给出i,a,k,c,(i+k*a<=len)也就是把字符串位置为i,i+a,i+2*a...,i+k*a的改成c字符,输出q次操作后的字符串。

首先暴力做法肯定是遍历字符串的每个位置,然后从后往前遍历,找到最后一个修改到这个位置的操作,但这样的时间复杂度是n*q,是1e10级别的,很明显不行。然后看提交里一位大佬的代码,才明白是怎么个做法。

我们的入手点就在i+k*a<=len这里,i基本没啥影响我们不管i,直接看k*a,设n为√len,那么如果k<=n,我们就直接更新,此时是n*q,是3e7级别的。

那么对于k>n的,此时a<=n,我们就遍历a从1到n,对每个a进行考虑,相同a的按照操作次序从后往前的顺序进行遍历,因为是相同的a,那么同一个位置的下一个位置也是一样的,

所以我们可以用一个并查集的区间合并进行跳转,这样对于相同的a,字符串的每个位置只会被遍历到一个,此时是n*len*并查集find小于log的一个复杂度。

 1 #include<cstdio>
 2 #include<cmath> 
 3 #include<cstring>
 4 #include<vector>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 const int N=1e5+11;
 9 struct Node{
10     int p,a,k,id;
11     Node(){}
12     Node(int p,int a,int k,int id):p(p),a(a),k(k),id(id){}
13 };
14 char mmp[N],mmk[N];
15 int ans[N],fa[N];
16 vector<Node> vv;
17 void init(int n){
18     vv.clear();
19     for(int i=0;i<=n;i++) ans[i]=0;
20 } 
21 int find(int x){
22     return fa[x]==x ? x : fa[x]=find(fa[x]); 
23 }
24 int main(){
25     int lens,n,q,p,a,kk;
26     while(~scanf("%s%d",mmp+1,&q)){
27         lens=strlen(mmp+1);
28         n=sqrt(lens);
29         init(lens);
30         for(int i=1;i<=q;i++){
31             scanf("%d%d%d %c",&p,&a,&kk,&mmk[i]);
32             if(kk<=n){
33                 for(int j=0;j<=kk;j++) ans[p+j*a]=max(ans[p+j*a],i);
34                 continue;
35             }
36             vv.push_back(Node(p,a,kk,i));
37         }
38         for(int i=1;i<=n;i++){
39             for(int j=1;j<=lens+1;j++) fa[j]=j;
40             for(int j=(int)vv.size()-1;j>=0;j--){
41                 if(vv[j].a!=i) continue;
42                 for(int k=find(vv[j].p),lim=vv[j].p+vv[j].k*vv[j].a;k<=lim;k=find(k)){
43                     ans[k]=max(ans[k],vv[j].id);
44                     fa[k]=k+i<=lens ? find(k+i) : lens+1; 
45                 }
46             }
47         }
48         for(int i=1;i<=lens;i++) if(ans[i]) mmp[i]=mmk[ans[i]];
49         printf("%s\n",mmp+1);
50     }
51     return 0;
52 }
分类讨论

猜你喜欢

转载自www.cnblogs.com/LMCC1108/p/11674619.html