【数轴涂色+并查集路径压缩+加速】C. String Reconstruction

http://codeforces.com/contest/828/problem/C

【题意】

【思路】

  • 因为题目保证一定有解,所有优化时间复杂度的关键就是不要重复染色,所以我们可以用并查集维护区间,把确定的点的父亲节点设为下一个点,这样访问过的点的根节点都是没访问过的点。
  • 与上一题是同样的思路,用并查集路径压缩,
  • 要求字典序最小,可以最初给每个字符都赋值'a'
  • 判断字符串最长是多少,最后加'\0'

【Accepted】

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<set>
 8 #include<queue>
 9 using namespace std;
10 const int N=1e6+3;
11 const int maxn=2*N;
12 const int inf=0x3f3f3f3f;
13 int fa[maxn];
14 int n,m;
15 int a[maxn];
16 char str[maxn];
17 char ans[maxn];
18 int find(int x)
19 {
20     return fa[x]==x?x:fa[x]=find(fa[x]);
21 }
22 
23 void init()
24 {
25     for(int i=0;i<maxn;i++){
26         fa[i]=i;
27     }
28 }
29 int main()
30 {
31     while(~scanf("%d",&n))
32     {
33         init();
34         memset(ans,'a',sizeof(ans));
35         int mmax=-inf;
36         for(int i=0;i<n;i++)
37         {
38             scanf("%s%d",str,&m);
39             int len=strlen(str);
40             int v=-inf;
41             for(int k=0;k<m;k++)
42             {
43                 scanf("%d",&a[k]);
44                 v=max(v,a[k]);
45             }
46             mmax=max(mmax,v+len);
47             for(int k=0;k<m;k++)
48             {
49                 int x=a[k];
50                 int y=a[k]+len-1;
51                 while((x=find(x))<=y)
52                 {
53                     ans[x]=str[x-a[k]];
54                     fa[x]=x+1;
55                 }
56             }
57         }
58         ans[mmax]='\0';
59         cout<<ans+1<<endl;
60 
61         
62     }
63     return 0;
64 }
View Code

或者

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<set>
 8 #include<queue>
 9 using namespace std;
10 const int N=1e6+3;
11 const int maxn=2*N;
12 const int inf=0x3f3f3f3f;
13 int fa[maxn];
14 int n,m;
15 int a[maxn];
16 char str[maxn];
17 char ans[maxn];
18 int find(int x)
19 {
20     return fa[x]==x?x:fa[x]=find(fa[x]);
21 }
22 
23 void init()
24 {
25     for(int i=0;i<maxn;i++){
26         fa[i]=i;
27     }
28 }
29 int main()
30 {
31     while(~scanf("%d",&n))
32     {
33         init();
34         memset(ans,'a',sizeof(ans));
35         int mmax=-inf;
36         for(int i=0;i<n;i++)
37         {
38             scanf("%s%d",str,&m);
39             int len=strlen(str);
40             for(int k=0;k<m;k++)
41             {
42                 scanf("%d",&a[k]);
43             }
44             mmax=max(mmax,a[m-1]+len);
45             for(int k=0;k<m;k++)
46             {
47                 int x=a[k];
48                 int y=a[k]+len-1;
49                 while((y=find(y))!=find(x-1))
50                 {
51                     ans[y]=str[y-a[k]];
52                     fa[y]=fa[y-1];
53                 }
54             }
55         }
56         ans[mmax]='\0';
57         cout<<ans+1<<endl;
58 
59         
60     }
61     return 0;
62 }
View Code

从右往左或从左往右合并都一样。

一开始在数据8上T了好几回,原来并查集的find一开始没注意没有路径压缩..........

 

posted @ 2017-07-15 22:04  shulin15  阅读(243)  评论(0编辑  收藏  举报