【数轴涂色+并查集路径压缩+加速】C. String Reconstruction
http://codeforces.com/contest/828/problem/C
【题意】
【思路】
- 因为题目保证一定有解,所有优化时间复杂度的关键就是不要重复染色,所以我们可以用并查集维护区间,把确定的点的父亲节点设为下一个点,这样访问过的点的根节点都是没访问过的点。
- 与上一题是同样的思路,用并查集路径压缩,
- 要求字典序最小,可以最初给每个字符都赋值'a'
- 判断字符串最长是多少,最后加'\0'
【Accepted】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
或者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
从右往左或从左往右合并都一样。
一开始在数据8上T了好几回,原来并查集的find一开始没注意没有路径压缩..........