1. 程式人生 > >VK CUP 2017 CString Reconstruction

VK CUP 2017 CString Reconstruction

def base pre putchar size 區間 bsp const can

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals)

從給出信息片段,得出字典序最小的一個字符串,題目保證答案存在

信息給出形式:

3    
a 4 1 3 5 7
ab 2 1 5
ca 1 4

第一行 3 代表信息片段個數
第二行 a 代表片段信息, 4 代表在4個地方出現 1,3,5,7 分別代表出現的位置
.
.
輸出:

abacaba

題目給出片段信息和出現位置,相當於給出區間

為避免對已操作區間重復操作,用樹狀數組加以標記,標記方式為,訪問標記為1,未訪問為0,樹狀數組求和,若某區間的和不與區間長度相等,則該區間未標記完全.

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 2001000;
 6 
 7 char ans[maxn];
 8 char c[maxn];
 9 int t[maxn];
10 
11 void add(int k)
12 {
13     while(k <= maxn)
14     {
15         t[k]++;
16         k += k & -k;
17     }
18 }
19 int sum(int l, int r)
20 {
21     l--;      //左右都包括
22     int suml = 0;
23     while(l)
24     {
25         suml += t[l];
26         l -= l & -l;
27     }
28     int sumr = 0;
29     while(r)
30     {
31         sumr += t[r];
32         r -= r & -r;
33     }
34     return sumr - suml;
35 }
36 
37 void updata(int l, int r, int k)
38 {
39     if(l == r)
40     {
41         if(!ans[l])
42         {
43             add(l);
44             ans[l] = c[k];
45         }
46         return ;
47     }
48     int mid = (l + r) >> 1;
49     if(sum(l, mid) < mid - l + 1) updata(l, mid, k);
50     if(sum(mid + 1, r) < r - mid) updata(mid + 1, r, k + mid - l + 1);
51 }
52 
53 int main()
54 {
55     int n;
56     while(scanf("%d", &n) != EOF)
57     {
58         int lans = 0;
59         memset(ans,0,sizeof(ans));
60         memset(t,0,sizeof(t));
61         while(n--)
62         {
63             int m = 0;
64             scanf("%s%d", c, &m);
65             int len = strlen(c);
66             for(int i = 0; i < m; i++)
67             {
68                 int l = 0;
69                 scanf("%d", &l);
70                 lans = max(lans, l + len);
71                 updata(l, l + len - 1, 0);
72             }
73         }
74         for(int i = 1; i < lans; i++)
75         {
76             putchar(ans[i]? ans[i]: ‘a‘);
77         }
78         printf("\n");
79     }
80     return 0;
81 }

用並查集標記已被訪問區域,標記方式為,已被訪問區域所有元素的根設為最近未被訪問的元素,這樣不僅標記了訪問區域,訪問時還提供一個到未訪問區域的方向.

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 2000100;
 6 
 7 char ans[maxn];
 8 char c[maxn];
 9 int fa[maxn];
10 
11 int f(int x)
12 {
13     return x == fa[x] ? x : fa[x] = f(fa[x]);
14
} 15 16 int main() 17 { 18 int n; 19 while(scanf("%d", &n) != EOF) 20 { 21 int lans = 0; 22 memset(ans,0,sizeof(ans)); 23 for(int i = 0; i < maxn; i++) fa[i] = i; 24 while(n--) 25 { 26 int m = 0; 27 scanf("%s%d", c, &m); 28 int len = strlen(c); 29 for(int i = 0; i < m; i++) 30 { 31 int l = 0; 32 scanf("%d", &l); 33 lans = max(lans,l+len); 34 for(int j = f(l); j < l + len; j++) 35 { 36 fa[j] = max(f(l + len),fa[j]); 37 ans[j] = c[j-l]; 38 } 39 } 40 } 41 for(int i = 1; i < lans; i++) 42 { 43 putchar(ans[i]? ans[i] : a); 44 } 45 printf("\n"); 46 } 47 return 0; 48 }

VK CUP 2017 CString Reconstruction