AtCoder Grand Contest 014 题解

本文解析了六道经典算法题目,包括CookieExchanges、UnplannedQueries、ClosedRooms、BlackandWhiteTree、BlueandRedTree及StrangeSorting。通过直接模拟、异或运算、启发式合并等方法解决循环检测、图遍历、树形结构分析等问题。
摘要由CSDN通过智能技术生成

A - Cookie Exchanges

直接模拟即可,如果出现循环了那就GG了。

 1 //waz
 2 #include <bits/stdc++.h>
 3  
 4 using namespace std;
 5  
 6 #define mp make_pair
 7 #define pb push_back
 8 #define fi first
 9 #define se second
10 #define ALL(x) (x).begin(), (x).end()
11 #define SZ(x) ((int)((x).size()))
12  
13 typedef pair<int, int> PII;
14 typedef vector<int> VI;
15 typedef long long int64;
16 typedef unsigned int uint;
17 typedef unsigned long long uint64;
18  
19 #define gi(x) ((x) = F())
20 #define gii(x, y) (gi(x), gi(y))
21 #define giii(x, y, z) (gii(x, y), gi(z))
22  
23 int F()
24 {
25     char ch;
26     int x, a;
27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
28     if (ch == '-') ch = getchar(), a = -1;
29     else a = 1;
30     x = ch - '0';
31     while (ch = getchar(), ch >= '0' && ch <= '9')
32         x = (x << 1) + (x << 3) + ch - '0';
33     return a * x;
34 }
35  
36 int A, B, C;
37  
38 map<pair<PII,int>, bool> h;
39  
40 int cnt = 0;
41  
42 int main()
43 {
44     giii(A, B, C);
45     while (1)
46     {
47         if ((A & 1) || (B & 1) || (C & 1))
48         {
49             printf("%d\n", cnt);
50             return 0;
51         }
52         if (h.count(mp(mp(A, B), C)))
53         {
54             puts("-1");
55             return 0;
56         }
57         ++cnt;
58         int a = A, b = B, c = C;
59         h[mp(mp(A, B), C)] = 1;
60         A = (b + c) >> 1;
61         B = (a + c) >> 1;
62         C = (a + b) >> 1; 
63     }
64 } 

 

B - Unplanned Queries

我们发现本质就是异或,判断能不能边全为0,我们发现异或操作lca是不会变的,那么我们只要算出每个点出现次数是不是偶数就好了。

 1 //waz
 2 #include <bits/stdc++.h>
 3  
 4 using namespace std;
 5  
 6 #define mp make_pair
 7 #define pb push_back
 8 #define fi first
 9 #define se second
10 #define ALL(x) (x).begin(), (x).end()
11 #define SZ(x) ((int)((x).size()))
12  
13 typedef pair<int, int> PII;
14 typedef vector<int> VI;
15 typedef long long int64;
16 typedef unsigned int uint;
17 typedef unsigned long long uint64;
18  
19 #define gi(x) ((x) = F())
20 #define gii(x, y) (gi(x), gi(y))
21 #define giii(x, y, z) (gii(x, y), gi(z))
22  
23 int F()
24 {
25     char ch;
26     int x, a;
27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
28     if (ch == '-') ch = getchar(), a = -1;
29     else a = 1;
30     x = ch - '0';
31     while (ch = getchar(), ch >= '0' && ch <= '9')
32         x = (x << 1) + (x << 3) + ch - '0';
33     return a * x;
34 }
35  
36 int w[100010];
37  
38 int n, m;
39  
40 int main()
41 {
42     gii(n, m);
43     for (int i = 1; i <= m; ++i)
44     {
45         int u, v;
46         gii(u, v);
47         w[u] ^= 1;
48         w[v] ^= 1;
49     }
50     for (int i = 1; i <= n; ++i)
51     {
52         if (w[i])
53         {
54             puts("NO");
55             return 0;
56         }
57     }
58     puts("YES");
59     return 0;
60 }

 

C - Closed Rooms

走完一次之后,后面肯定可以直接开锁不用绕圈子。算出k步之内能走到哪,直接和到边界距离加起来就好了。

  1 //waz
  2 #include <bits/stdc++.h>
  3  
  4 using namespace std;
  5  
  6 #define mp make_pair
  7 #define pb push_back
  8 #define fi first
  9 #define se second
 10 #define ALL(x) (x).begin(), (x).end()
 11 #define SZ(x) ((int)((x).size()))
 12  
 13 typedef pair<int, int> PII;
 14 typedef vector<int> VI;
 15 typedef long long int64;
 16 typedef unsigned int uint;
 17 typedef unsigned long long uint64;
 18  
 19 #define gi(x) ((x) = F())
 20 #define gii(x, y) (gi(x), gi(y))
 21 #define giii(x, y, z) (gii(x, y), gi(z))
 22  
 23 int F()
 24 {
 25     char ch;
 26     int x, a;
 27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
 28     if (ch == '-') ch = getchar(), a = -1;
 29     else a = 1;
 30     x = ch - '0';
 31     while (ch = getchar(), ch >= '0' && ch <= '9')
 32         x = (x << 1) + (x << 3) + ch - '0';
 33     return a * x;
 34 }
 35  
 36 int h, w, k;
 37  
 38 char str[810][810];
 39  
 40 int d[810][810];
 41  
 42 PII operator + (const PII &a, const PII &b) { return mp(a.fi + b.fi, a.se + b.se); }
 43  
 44 bool check(const PII &a) { return a.fi >= 1 && a.fi <= h && a.se >= 1 && a.se <= w && str[a.fi][a.se] != '#'; }
 45  
 46 int main()
 47 {
 48     memset(d, 63, sizeof d);
 49     giii(h, w, k);
 50     for (int i = 1; i <= h; ++i) scanf("%s", str[i] + 1);
 51     int l = 0, r = 0;
 52     static PII q[810 * 810];
 53     for (int i = 1; i <= h; ++i)
 54         for (int j = 1; j <= w; ++j)
 55             if (str[i][j] == 'S')
 56                 q[r++] = mp(i, j), d[i][j] = 0;
 57     while (l < r)
 58     {
 59         PII u = q[l++];
 60         if (check(u + mp(1, 0)))
 61         {
 62             PII v = u + mp(1, 0);
 63             if (d[v.fi][v.se] > d[u.fi][u.se] + 1)
 64             {
 65                 d[v.fi][v.se] = d[u.fi][u.se] + 1;
 66                 q[r++] = v;
 67             }
 68         }
 69         if (check(u + mp(-1, 0)))
 70         {
 71             PII v = u + mp(-1, 0);
 72             if (d[v.fi][v.se] > d[u.fi][u.se] + 1)
 73             {
 74                 d[v.fi][v.se] = d[u.fi][u.se] + 1;
 75                 q[r++] = v;
 76             }
 77         }
 78         if (check(u + mp(0, 1)))
 79         {
 80             PII v = u + mp(0, 1);
 81             if (d[v.fi][v.se] > d[u.fi][u.se] + 1)
 82             {
 83                 d[v.fi][v.se] = d[u.fi][u.se] + 1;
 84                 q[r++] = v;
 85             }
 86         }
 87         if (check(u + mp(0, -1)))
 88         {
 89             PII v = u + mp(0, -1);
 90             if (d[v.fi][v.se] > d[u.fi][u.se] + 1)
 91             {
 92                 d[v.fi][v.se] = d[u.fi][u.se] + 1;
 93                 q[r++] = v;
 94             }
 95         }
 96     }
 97     int ans = d[0][0];
 98     for (int i = 1; i <= h; ++i)
 99     {
100         for (int j = 1; j <= w; ++j)
101         {
102             int v = min(min(i - 1, h - i), min(j - 1, w - j));
103             if (!v && d[i][j] <= k) ans = 1;
104             if (d[i][j] <= k) ans = min(ans, 1 + (v - 1) / k + 1);
105         }
106     }
107     printf("%d\n", ans);
108     return 0;
109 }

 

D - Black and White Tree

如果树是奇数个点的,肯定先手胜。

我们来证明这个结论,可以用归纳。

首先n=1时成立。

接着我们可以找到一个点,使得树分成两个及以上奇数的部分,如果后手染其中一棵,你就往另一棵递归。

那么很显然,偶数的时候只要能找到这么一个点也能胜利。

 1 //waz
 2 #include <bits/stdc++.h>
 3  
 4 using namespace std;
 5  
 6 #define mp make_pair
 7 #define pb push_back
 8 #define fi first
 9 #define se second
10 #define ALL(x) (x).begin(), (x).end()
11 #define SZ(x) ((int)((x).size()))
12  
13 typedef pair<int, int> PII;
14 typedef vector<int> VI;
15 typedef long long int64;
16 typedef unsigned int uint;
17 typedef unsigned long long uint64;
18  
19 #define gi(x) ((x) = F())
20 #define gii(x, y) (gi(x), gi(y))
21 #define giii(x, y, z) (gii(x, y), gi(z))
22  
23 int F()
24 {
25     char ch;
26     int x, a;
27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
28     if (ch == '-') ch = getchar(), a = -1;
29     else a = 1;
30     x = ch - '0';
31     while (ch = getchar(), ch >= '0' && ch <= '9')
32         x = (x << 1) + (x << 3) + ch - '0';
33     return a * x;
34 }
35  
36 const int N = 1e5 + 10; 
37  
38 int n;
39  
40 int siz[N];
41  
42 VI edge[N];
43  
44 bool ok;
45  
46 void dfs(int u, int fa)
47 {
48     siz[u] = 1;
49     int cnt = 0;
50     for (auto v : edge[u])
51     {
52         if (v == fa) continue;
53         dfs(v, u);
54         siz[u] += siz[v];
55         cnt += (siz[v] & 1);
56     }
57     cnt += ((n - siz[u]) & 1);
58     if (cnt > 1) ok = 1;
59 }
60  
61 int main()
62 {
63     gi(n);
64     for (int i = 1; i < n; ++i)
65     {
66         int u, v;
67         gii(u, v);
68         edge[u].pb(v);
69         edge[v].pb(u); 
70     }
71     dfs(1, 0);
72     if (n & 1) ok = 1;
73     puts(ok ? "First" : "Second");
74     return 0;
75 }

 

E - Blue and Red Tree

最后删的边肯定两棵树都出现过,我们就倒着模拟,合并的时候用启发式合并就好了。

  1 //waz
  2 #include <bits/stdc++.h>
  3  
  4 using namespace std;
  5  
  6 #define mp make_pair
  7 #define pb push_back
  8 #define fi first
  9 #define se second
 10 #define ALL(x) (x).begin(), (x).end()
 11 #define SZ(x) ((int)((x).size()))
 12  
 13 typedef pair<int, int> PII;
 14 typedef vector<int> VI;
 15 typedef long long int64;
 16 typedef unsigned int uint;
 17 typedef unsigned long long uint64;
 18  
 19 #define gi(x) ((x) = F())
 20 #define gii(x, y) (gi(x), gi(y))
 21 #define giii(x, y, z) (gii(x, y), gi(z))
 22  
 23 int F()
 24 {
 25     char ch;
 26     int x, a;
 27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
 28     if (ch == '-') ch = getchar(), a = -1;
 29     else a = 1;
 30     x = ch - '0';
 31     while (ch = getchar(), ch >= '0' && ch <= '9')
 32         x = (x << 1) + (x << 3) + ch - '0';
 33     return a * x;
 34 }
 35  
 36 const int N = 1e5 + 10;
 37  
 38 map<int, int> h[N];
 39  
 40 set<int> edge[N];
 41  
 42 queue<PII> q;
 43  
 44 void link(int u, int v)
 45 {
 46     edge[u].insert(v);
 47     edge[v].insert(u);
 48     if (u > v) swap(u, v);
 49     ++h[u][v];
 50     if (h[u][v] == 2)
 51     {
 52         q.push(mp(u,v));
 53     }
 54     if (h[u][v] > 2)
 55     {
 56         puts("NO");
 57         exit(0);
 58     }
 59 }
 60  
 61 void cut(int u, int v)
 62 {
 63     edge[u].erase(v);
 64     if (u > v) swap(u, v); 
 65     h[u].erase(v);
 66 }
 67  
 68 int fa[N], n;
 69  
 70 int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
 71  
 72 int main()
 73 {
 74     gi(n);
 75     for (int i = 1; i <= n; ++i) fa[i] = i;
 76     for (int i = 1; i < n; ++i)
 77     {
 78         int u, v;
 79         gii(u, v);
 80         link(u, v);
 81     }
 82     for (int i = 1; i < n; ++i)
 83     {
 84         int u, v;
 85         gii(u, v);
 86         link(u, v);
 87     }
 88     for (int i = 1; i < n; ++i)
 89     {
 90         int u, v;
 91         do
 92         {
 93             if (q.empty())
 94             {
 95                 puts("NO");
 96                 return 0;
 97             }
 98             u = q.front().fi;
 99             v = q.front().se;
100             u = find(u);
101             v = find(v);
102             q.pop();
103         } while (u == v);
104         if (SZ(edge[u]) > SZ(edge[v])) swap(u, v);
105         fa[u] = v;
106         cut(v, u);
107         for (auto x : edge[u])
108         {
109             x = find(x);
110             if (x == v) continue;
111             link(x, v);
112             cut(x, u);
113         }
114         edge[u].clear();
115     }
116     puts("YES");
117     return 0;
118 } 

 

F - Strange Sorting

找规律+递推。。。

 1 //waz
 2 #include <bits/stdc++.h>
 3  
 4 using namespace std;
 5  
 6 #define mp make_pair
 7 #define pb push_back
 8 #define fi first
 9 #define se second
10 #define ALL(x) (x).begin(), (x).end()
11 #define SZ(x) ((int)((x).size()))
12  
13 typedef pair<int, int> PII;
14 typedef vector<int> VI;
15 typedef long long int64;
16 typedef unsigned int uint;
17 typedef unsigned long long uint64;
18  
19 #define gi(x) ((x) = F())
20 #define gii(x, y) (gi(x), gi(y))
21 #define giii(x, y, z) (gii(x, y), gi(z))
22  
23 int F()
24 {
25     char ch;
26     int x, a;
27     while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
28     if (ch == '-') ch = getchar(), a = -1;
29     else a = 1;
30     x = ch - '0';
31     while (ch = getchar(), ch >= '0' && ch <= '9')
32         x = (x << 1) + (x << 3) + ch - '0';
33     return a * x;
34 }
35  
36 const int N = 2e5 + 10;
37  
38 int n, p[N], f[N], t[N];
39  
40 bool ck(int a, int b, int c)
41 {
42     return (a < b && b < c) || (b < c && c < a) || (c < a && a < b);
43 }
44  
45 int main()
46 {
47     gi(n);
48     for (int i = 1; i <= n; ++i) p[F()] = i;
49     for (int i = n - 1; i; --i)
50     {
51         if (!t[i + 1])
52         {
53             if (p[i] > p[i + 1]) t[i] = 1, f[i] = i + 1;
54         }
55         else
56         {
57             if (ck(p[f[i + 1]], p[i], p[i + 1])) t[i] = t[i + 1], f[i] = f[i + 1];
58             else t[i] = t[i + 1] + 1, f[i] = i + 1;
59         }
60     }
61     printf("%d\n", t[1]);
62     return 0;
63 }

 

转载于:https://www.cnblogs.com/AnzheWang/p/9686356.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值