2017-2018 ACM-ICPC Latin American Regional Programming Contest Solution

A - Arranging tiles

留坑。

B - Buggy ICPC

题意:给出一个字符串,然后有两条规则,如果打出一个辅音字母,直接接在原字符串后面,如果打出一个元音字母,那么接在原来的字符串后面之后再翻转整个字符串,在这两条规则之下,求有多少种打印给定字符串的方法

思路:如果第一个字符是辅音,那么答案为0

如果全是辅音或全是元音,那么答案为1

如果只有一个辅音,答案为len

否则是最中间两个元音中间的辅音字符个数+1

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 100010
 6 
 7 char s[N];
 8 
 9 bool vis[210];
10 
11 inline void Init()
12 {
13     vis['a'] = 1;
14     vis['e'] = 1;
15     vis['i'] = 1;
16     vis['o'] = 1;
17     vis['u'] = 1;
18 }
19 
20 inline int work()
21 {
22     int len = strlen(s);
23     if (len == 1) return 1;
24     int cnt = 0;
25     for (int i = 0; i < len; ++i) if (vis[s[i]]) cnt++; 
26     if (cnt == 0 || cnt == len) return 1;
27     if (!vis[s[0]]) return 0;
28     if (cnt == 1) return len;
29     int l = 0, r = len - 1;
30     while (vis[s[r]] == 0) --r;
31     int flag = 0;
32     for (; true; flag ^= 1)
33     {
34         cnt = 0;    
35         if (flag == 0)
36         {
37             ++l;
38             while (true)
39             {
40                 if (l == r) return cnt + 1;
41                 if (vis[s[l]]) break; 
42                 ++cnt;++l;
43             }
44         }
45         else
46         {
47             --r;
48             while (true)
49             {
50                 if (l == r) return cnt + 1;
51                 if (vis[s[r]]) break;
52                 ++cnt;--r;
53             }
54         }
55     }
56 }
57 
58 int main()
59 {
60     Init();
61     while (scanf("%s", s) != EOF)
62     {
63         printf("%d\n", work());
64     }
65     return 0;
66 }
View Code

C - Complete Naebbirac's sequence

题意:可以有三种操作, 一种是可以加上一个数,一种是可以减去一个数,一种是可以改变一个数 使得所有数出现次数相同,只能有一个操作,如果不能完成,输出"*"

思路:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e3 + 10;
 6 const int INF = 0x3f3f3f3f;
 7 
 8 int k, n;
 9 int arr[maxn];
10 int Max, Min, Mx, Mn;
11 
12 inline bool check()
13 {
14     for(int i = 2; i <= k; ++i)
15     {
16         if(arr[i] != arr[1]) return false;
17     }
18     return true;
19 }
20 
21 int main()
22 {
23     while(~scanf("%d %d", &k, &n))
24     {
25         memset(arr, 0, sizeof arr);
26         for(int i = 0 , num; i < n; ++i)
27         {
28             scanf("%d", &num);
29             arr[num]++;
30         }
31         Max = -INF, Min = INF;
32         for(int i = 1; i <= k; ++i)
33         {
34             if(arr[i] > Max)
35             {
36                 Max = arr[i];
37                 Mx = i;
38             }
39             if(arr[i] < Min)
40             {
41                 Min = arr[i];
42                 Mn = i;
43             }
44         }
45         if((n - 1) % k == 0)
46         {
47             --arr[Mx];
48             if(check())
49             {
50                 printf("-%d\n", Mx);
51                 continue;
52             }
53             ++arr[Mx];
54         }
55         if((n + 1) % k == 0)
56         {
57             ++arr[Mn];
58             if(check())
59             {
60                 printf("+%d\n", Mn);
61                 continue;
62             }
63             --arr[Mn];
64         }
65         ++arr[Mn];
66         --arr[Mx];
67         if(check())
68         {
69             printf("-%d +%d\n", Mx, Mn);
70             continue;
71         }
72         printf("*\n");
73 
74     }
75     return 0;
76 }
View Code

D - Daunting device

留坑。

E - Enigma

题意:给出两个数,有一个数中某些位是空的,填充空的位,使得左边那个数能够整除右边的数,并且左边那个数最小

思路:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e3 + 10;
 6 
 7 bool flag[maxn][maxn];
 8 int vis[maxn][maxn];
 9 string str;
10 string ans;
11 int len;
12 int m;
13 
14 inline bool DFS(int idx, int res)
15 {
16     if(idx >= len)
17     {
18         return res == 0;
19     }
20     if(vis[idx][res] != -1) return flag[idx][res];
21     vis[idx][res] = 1;
22     bool &ret = flag[idx][res];
23     if(str[idx] == '?')
24     {
25         for(int i = !idx; i <= 9; ++i)
26         {
27             ret |= DFS(idx + 1, (res * 10 + i) % m);
28             if(ret) return true;
29         }
30         return false;
31     }
32     else
33     {
34         ret |= DFS(idx + 1, (res * 10 + (str[idx] - '0')) % m);
35     }
36     return ret;
37 }
38 
39 inline void WORK(int idx,int res)
40 {
41     if(idx == len) return ;
42     if(str[idx] == '?')
43     {
44         for(int i = !idx; i <= 9; ++i)
45         {
46             if(DFS(idx + 1, (res * 10 + i) % m))
47             {
48                 ans += (char)(i + '0');
49                 WORK(idx + 1, (res * 10 + i) % m);
50                 return ;
51             }
52         }
53     }
54     else
55     {
56         ans += str[idx];
57         WORK(idx + 1, (res * 10 + str[idx] - '0') % m);
58         return ;
59     }
60 }
61 
62 int main()
63 {
64     ios::sync_with_stdio(false);
65     cin.tie(0);
66     cout.tie(0);
67     while(cin >> str >> m)
68     {
69         memset(flag, 0, sizeof flag);
70         memset(vis, -1, sizeof vis);
71         len = str.length();
72         if(DFS(0, 0))
73         {
74             ans.clear();
75             WORK(0, 0);
76             cout << ans << "\n";
77         }
78         else
79         {
80             cout << "*\n";
81         }
82     }
83     return 0;
84 }
View Code

F - Fundraising

题意:每个人有两个值,以及一个权值,若两个人都能选出来,那么要么两个人的值都相同,或者某个人的两个值分别大于另一个人,求选出一些人使得权值和最大

思路:两个值都相同的先合并,然后按一维排序,另一维做最大上升子序列权值和

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 100010
 6 #define ll long long
 7 typedef pair <int, int> pii;
 8 
 9 struct node
10 {
11     int x, y; ll D;
12     inline node() {}
13     inline node(int x, int y, ll D) : x(x), y(y), D(D) {}
14     inline bool operator < (const node &r) const
15     {
16         return x < r.x || x == r.x && y > r.y; 
17     }
18 }arr[N];
19 
20 map <pii, int> mp;
21 int n, m, cnt;
22 ll brr[N], a[N];
23 
24 inline int Get(pii x)
25 {
26     if (mp.find(x) == mp.end())
27     {
28         mp[x] = ++cnt;
29         brr[cnt] = x.second;
30         arr[cnt] = node(x.first, x.second, 0); 
31     }
32     return mp[x]; 
33 }
34 
35 inline void Init()
36 {
37     memset(a, 0, sizeof a);
38     sort(brr + 1, brr + 1 + cnt); 
39     m = unique(brr + 1, brr + 1 + cnt) - brr - 1;
40 }
41 
42 inline int lowbit(int x)
43 {
44     return x & (-x); 
45 }
46 
47 inline void update(int x, ll val)
48 {
49     for (int i = x; i <= m; i += lowbit(i))
50         a[i] = max(a[i], val);
51 }
52 
53 inline ll query(int x)
54 {
55     ll res = 0;
56     for (int i = x; i > 0; i -= lowbit(i))
57         res = max(res, a[i]);
58     return res;
59 }
60 
61 int main()
62 {
63     while (scanf("%d", &n) != EOF)
64     {
65         mp.clear(); cnt = 0;
66         int x, y; ll D;
67         for (int i = 1; i <= n; ++i)
68         {
69             scanf("%d%d%lld", &x, &y, &D);
70             int pos = Get(pii(x, y));
71             arr[pos].D += D;
72         }
73         Init();
74         for (int i = 1; i <= cnt; ++i) arr[i].y = lower_bound(brr + 1, brr + 1 + m, arr[i].y) - brr;
75         sort(arr + 1, arr + 1 + cnt);
76         for (int i = 1; i <= cnt; ++i)
77         {
78             ll v = query(arr[i].y - 1);
79                update(arr[i].y, v + arr[i].D);    
80         }
81         printf("%lld\n", query(m));
82     }
83     return 0;    
84 }
View Code

G - Gates of uncertainty

留坑。

H - Hard choice

水。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int a[3], b[3];
 6 
 7 int main()
 8 {
 9     while (scanf("%d%d%d", &a[0], &a[1], &a[2]) != EOF)
10     {
11         for (int i = 0; i < 3; ++i) scanf("%d", b + i);
12         int ans = 0;
13         for (int i = 0; i < 3; ++i) ans += max(0, b[i] - a[i]);
14         printf("%d\n", ans);
15     }
16     return 0;
17 }
View Code

I - Imperial roads

题意:给出一张图,然后询问给出一条边,求有这条边的最小生成树的权值和

思路:先求最小生成树,然后询问的边如果在最小生成树里面那么就是原来的权值和,否则在原来的最小生成树里面的加入一条边,形成个环,然后去掉这个环里面除了加入的边之外的边权最大的边

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 2e5 + 10;
  6 const int DEG = 20;
  7 
  8 typedef long long ll;
  9 
 10 int n, m;
 11 
 12 struct node{
 13     int u, v;
 14     ll w;
 15     inline node(){}
 16     inline node(int u, int v, ll w) :u(u), v(v), w(w){}
 17     inline bool operator < (const node &b)const
 18     {
 19         return w < b.w;
 20     }
 21 };
 22 
 23 struct Edge{
 24     int to;
 25     int nxt;
 26     ll w;
 27     inline Edge(){}
 28     inline Edge(int to, int nxt, ll w) :to(to), nxt(nxt), w(w){}
 29 }edge[maxn << 1]; 
 30 
 31 int dis[maxn][DEG];
 32 bool inMST[maxn << 1];
 33 int head[maxn];
 34 int tot;
 35 int father[maxn];
 36 vector<node>G;
 37 int cnt;
 38 map<pair<int,int>, int>mp;
 39 
 40 inline void addedge(int u,int v, ll w)
 41 {
 42     edge[tot] = Edge(v, head[u], w);
 43     head[u] = tot++;
 44 }
 45 
 46 inline void Init()
 47 {
 48     G.clear();
 49     cnt = 0;
 50     tot = 0;
 51     memset(dis, 0, sizeof dis);
 52     memset(head, -1, sizeof head);
 53     for(int i = 1; i <= n; ++i)
 54     {
 55         father[i] = i;
 56     }
 57 }
 58 
 59 inline int find(int x)
 60 {
 61     return x == father[x] ? father[x] : father[x] = find(father[x]);
 62 }
 63 
 64 inline void mix(int x,int y)
 65 {
 66     x = find(x);
 67     y = find(y);
 68     if(x != y)
 69     {
 70         father[x] = y;
 71     }
 72 }
 73 
 74 inline bool same(int x,int y)
 75 {
 76     return find(x) == find(y);
 77 }
 78 
 79 inline ll MST()
 80 {
 81     mp.clear();
 82     ll res = 0;
 83     sort(G.begin(), G.end());
 84     memset(inMST, false, sizeof inMST);
 85     for(auto it : G)
 86     {
 87         int u = it.u;
 88         int v = it.v;
 89         mp[make_pair(v, u)] = cnt;
 90         mp[make_pair(u, v)] = cnt++;
 91     }
 92     for(auto it : G)
 93     {
 94         int u = it.u;
 95         int v = it.v;
 96         if(same(u, v)) continue;
 97         mix(u, v);
 98         inMST[mp[make_pair(u, v)]] = true;
 99         addedge(u, v, it.w);
100         addedge(v, u, it.w);
101         res += it.w;
102     }
103     return res;
104 }
105 
106 int fa[maxn][DEG];
107 int deg[maxn];
108 
109 inline void BFS(int root)
110 {
111     queue<int>q;
112     deg[root] = 0;
113     fa[root][0] = root;
114     q.push(root);
115     while(!q.empty())
116     {
117         int tmp = q.front();
118         q.pop();
119         for(int i = 1; i < DEG; ++i)
120         {
121             dis[tmp][i] = max(dis[tmp][i - 1], dis[fa[tmp][i - 1]][i - 1]);
122             fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1];
123         }
124         for(int i = head[tmp]; ~i; i = edge[i].nxt)
125         {
126             int v = edge[i].to;
127             if(v == fa[tmp][0]) continue;
128             deg[v] = deg[tmp] + 1;
129             fa[v][0] = tmp;
130             int id = mp[make_pair(tmp, v)];
131             dis[v][0] = G[id].w;
132             q.push(v);
133         }
134     }
135 }
136 
137 inline int LCA(int u,int v)
138 {
139     int res = 0;
140     if(deg[u] > deg[v])
141         swap(u, v);
142     int hu = deg[u],  hv = deg[v];
143     int tu = u, tv = v;
144     for(int det = hv - hu, i = 0; det; det >>= 1, ++i)
145     {
146         if(det & 1)
147         {
148             res = max(res, dis[tv][i]);
149             tv = fa[tv][i];
150         }
151     }
152     if(tu == tv) return res;
153     for(int i = DEG - 1; i >= 0; --i)
154     {
155         if(fa[tu][i] == fa[tv][i]) continue;
156         res = max(res, max(dis[tu][i], dis[tv][i]));
157         tu = fa[tu][i];
158         tv = fa[tv][i];
159     }
160     res = max(res, max(dis[tu][0], dis[tv][0]));
161     return res;
162 }
163 
164 int main()
165 {
166     while(~scanf("%d %d", &n , &m))
167     {
168         Init();
169         for(int i = 1; i <= m; ++i)
170         {
171             int u, v;
172             ll w;
173             scanf("%d %d %lld", &u, &v, &w);
174             G.push_back(node(u, v, w));
175         }
176         ll ans = MST();
177         BFS(1);
178         int q;
179         scanf("%d", &q);
180         while(q--)
181         {
182             int u, v;
183             scanf("%d %d", &u, &v);
184             int id = mp[make_pair(u, v)];
185             ll w = G[id].w;
186             if(inMST[id])
187             {
188                 printf("%lld\n", ans);
189             }
190             else
191             {
192                 ll res = LCA(u, v);
193                 printf("%lld\n", ans + w - res);
194             }
195         }
196     }
197     return 0;
198 }
View Code

J - Jumping frog

题意:给出一个字符串,是一个圆圈,'R' 代码岩石 'P' 代表池塘 有一只青蛙,随便从哪一个岩石出发,固定步数k,若能回到原来的位置,那么这个步数就是ok的,求有多少个步数是ok的

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e5 +10;
 6 
 7 bool flag[maxn];
 8 char str[maxn];
 9 
10 inline int gcd(int a, int b)
11 {
12     return b == 0? a : gcd(b, a % b);
13 }
14 
15 int main()
16 {
17     while(~scanf("%s", str))
18     {
19         memset(flag, false, sizeof flag);
20         int n = strlen(str);
21         for(int i = 1; i < n; ++i)
22         {
23             if(n % i != 0) continue;
24             for(int j = 0; j < i; ++j)
25             {
26                 bool tmp = true;
27                 for(int k = 0; k <= n / i; ++k)
28                 {
29                     if(str[(j + k * i) % n] == 'P')
30                     {
31                         tmp = false;
32                         break;
33                     }
34                 }
35                 if(tmp)
36                 {
37                     flag[i] = true;
38                     break;
39                 }
40             }
41         }
42         int ans = 0;
43         for(int i = 1; i < n; ++i)
44         {
45             if(flag[gcd(i, n)]) ans++;
46         }
47         printf("%d\n", ans);
48     }
49     return 0;
50 }
View Code

K - Keep it covered

留坑。

L - Linearville

留坑。

M - Marblecoin

留坑。

猜你喜欢

转载自www.cnblogs.com/Dup4/p/9574748.html