首页 > 代码库 > VK CUP 2017 CString Reconstruction

VK CUP 2017 CString Reconstruction

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