1. 程式人生 > >CodeForces 828C String Reconstruction(並查集思想)

CodeForces 828C String Reconstruction(並查集思想)

ack return set bsp amp turn struct ++ color

題意:給你n個串,給你每個串在總串中開始的每個位置,問你最小字典序總串。

思路:顯然這道題有很多重復填塗的地方,那麽這裏的時間花費就會特別高。

我們維護一個並查集fa,用fa[i]記錄從第i位置開始第一個沒填塗的位置,那每次都能跳過塗過的地方。每次填完當前格就去填find(fa[i + 1])。

ps:一定要合並,不然超時。

代碼:

#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<string>
#include
<sstream> #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define ll long long #define ull unsigned long long using namespace std; const int maxn = 1000000+5; const int seed = 131; const int MOD = 100013; const int INF = 0x3f3f3f3f; char ans[maxn*10]; int fa[maxn*10
]; char s[maxn]; int find(int x){ return fa[x] == x? x : fa[x] = find(fa[x]); } int main(){ int n,t; memset(ans,0,sizeof(ans)); scanf("%d",&n); for(int i = 0;i < maxn * 10;i++) fa[i] = i; int end = 1; while(n--){ scanf("%s%d",s,&t); int len = strlen(s);
while(t--){ int x; scanf("%d",&x); end = max(end,x + len - 1); for(int i = find(x);i <= x + len -1;i = find(i + 1)){ ans[i] = s[i - x]; int fx = find(i); int fy = find(i + 1); if(fx > fy) fa[fy] = fx; else fa[fx] = fy; } } } for(int i = 1;i <= end;i++) if(ans[i] != 0)printf("%c",ans[i]); else printf("a"); printf("\n"); return 0; }

CodeForces 828C String Reconstruction(並查集思想)