AtCoder Grand Contest 008 题解
Posted anzhewang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Grand Contest 008 题解相关的知识,希望对你有一定的参考价值。
A - Simple Calculator
模拟+分类讨论即可。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘); if (ch == ‘-‘) ch = getchar(), a = -1; else a = 1; x = ch - ‘0‘; while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘) x = (x << 1) + (x << 3) + ch - ‘0‘; return a * x; } int work(int x, int y) { if (x <= y) return y - x; else return x - y + 2; } int main() { int x, y; gii(x, y); printf("%d ", min(work(x, y), min(1 + work(-x, y), min(1 + work(x, -y), 2 + work(-x, -y))))); }
B - Contiguous Repainting
我们发现可以找到一段连续的k个,其它部分可以任意挑,连续的那一段要么全选要么全不选,枚举连续段在哪即可。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘); if (ch == ‘-‘) ch = getchar(), a = -1; else a = 1; x = ch - ‘0‘; while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘) x = (x << 1) + (x << 3) + ch - ‘0‘; return a * x; } int a[100010]; int64 s1[100010], s2[100010], ans; int main() { int n, k; gii(n, k); for (int i = 1; i <= n; ++i) gi(a[i]), s1[i] = s1[i - 1] + a[i], s2[i] = s2[i - 1] + (a[i] > 0 ? a[i] : 0); for (int i = 1; i <= n - k + 1; ++i) { int j = i + k - 1; long long s = s2[i - 1] + s2[n] - s2[j]; s += max(s1[j] - s1[i - 1], 0LL); ans = max(ans, s); } printf("%lld ", ans); return 0; }
C - Tetromino Tiling
我们发现只有1,2,4,5这四种才有可能组合出完整矩形,其中两个相同的可以组成4*2的,或者1 4 5各一个组成一个6*2的,两种情况取max就好。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘); if (ch == ‘-‘) ch = getchar(), a = -1; else a = 1; x = ch - ‘0‘; while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘) x = (x << 1) + (x << 3) + ch - ‘0‘; return a * x; } int a[7], b[7]; int64 ans = 0, res = 0; int main() { for (int i = 0; i < 7; ++i) gi(a[i]), b[i] = a[i]; ans += 4LL * (a[0] >> 1); a[0] &= 1; ans += 4LL * (a[3] >> 1); a[3] &= 1; ans += 4LL * (a[4] >> 1); a[4] &= 1; ans += 2LL * a[1]; a[1] = 0; if (a[0] && a[3] && a[4]) ans += 6; if (b[0] && b[3] && b[4]) --b[0], --b[3], --b[4], res += 6; res += 4LL * (b[0] >> 1); res += 4LL * (b[3] >> 1); res += 4LL * (b[4] >> 1); res += 2LL * b[1]; printf("%lld ", max(ans, res) >> 1); }
D - K-th K
按坐标排序后贪心放就好了。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘); if (ch == ‘-‘) ch = getchar(), a = -1; else a = 1; x = ch - ‘0‘; while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘) x = (x << 1) + (x << 3) + ch - ‘0‘; return a * x; } PII x[510]; int a[510 * 510]; int n; int main() { gi(n); for (int i = 1; i <= n; ++i) gi(x[i].fi), x[i].se = i; int k = 1; sort(x + 1, x + n + 1); for (int i = 1; i <= n; ++i) { a[x[i].fi] = x[i].se; for (int j = 1; j < x[i].se; ++j) { while (a[k]) ++k; a[k] = x[i].se; } if (k > x[i].fi) { puts("No"); return 0; } } k = 1; for (int i = 1; i <= n; ++i) { for (int j = x[i].se + 1; j <= n; ++j) { while (a[k]) ++k; if (k < x[i].fi) { puts("No"); return 0; } a[k] = x[i].se; } } puts("Yes"); for (int i = 1; i <= n * n; ++i) printf("%d ", a[i]); }
E - Next or Nextnext
不会做……先咕着。
F - Black Radius
计算出每个点和它父亲的d值最大多少是不同的,最后DP一下就好了。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘); if (ch == ‘-‘) ch = getchar(), a = -1; else a = 1; x = ch - ‘0‘; while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘) x = (x << 1) + (x << 3) + ch - ‘0‘; return a * x; } const int N = 2e5 + 10; VI edge[N]; char str[N]; int n, in[N], out[N], dfs_clock, fa[N], dep[N], d[N]; void dfs1(int u) { in[u] = ++dfs_clock; for (auto v : edge[u]) { if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); } out[u] = dfs_clock; } struct node { int l, r; int val, tag; void add(int x) { val += x; tag += x; } } t[N << 2]; void push_up(int o) { t[o].val = max(t[o << 1].val, t[o << 1 | 1].val); } void push_down(int o) { if (t[o].tag) { t[o << 1].add(t[o].tag); t[o << 1 | 1].add(t[o].tag); t[o].tag = 0; } } void build(int o, int l, int r) { t[o].l = l, t[o].r = r; if (l == r) { t[o].val = d[l]; return; } int mid = (l + r) >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r); push_up(o); } int query(int o, int l, int r) { if (t[o].r < l || r < t[o].l) return 0; if (l <= t[o].l && t[o].r <= r) return t[o].val; push_down(o); return max(query(o << 1, l, r), query(o << 1 | 1, l, r)); } void add(int o, int l, int r, int x) { if (t[o].r < l || r < t[o].l) return; if (l <= t[o].l && t[o].r <= r) return t[o].add(x); push_down(o); add(o << 1, l, r, x); add(o << 1 | 1, l, r, x); push_up(o); } /* int pa[N]; int find(int x) { return x == pa[x] ? x : pa[x] = find(pa[x]); } void unit(int x, int y) { x = find(x), y = find(y); if (x == y) return; pa[x] = y; str[y] |= str[x]; } */ int mxt[N], mxa[N], mxb[N]; void dfs2(int u) { int a = query(1, in[u], out[u]) + 1; int b = max(query(1, 1, in[u] - 1), query(1, out[u] + 1, n)); if (fa[u]) mxt[u] = min(a + 1, b), mxa[u] = a + 1, mxb[u] = b; else mxt[u] = a; // >= t[u] : GG for (auto v : edge[u]) { if (v == fa[u]) continue; add(1, in[v], out[v], -1); add(1, 1, in[v] - 1, 1); add(1, out[v] + 1, n, 1); dfs2(v); add(1, in[v], out[v], 1); add(1, 1, in[v] - 1, -1); add(1, out[v] + 1, n, -1); } } int64 ans; int num[N]; void dfs3(int u) { //cerr << u << ", " << mxt[u] << " : " << mxa[u] << ", " << mxb[u] << endl; for (auto v : edge[u]) { if (v == fa[u]) continue; dfs3(v); if (mxt[v] > num[v]) ans += mxt[v] - num[v], num[u] = min(num[u], min(mxa[v] - 1, mxb[v] + 1)); else num[u] = min(num[u], num[v]); } } int main() { gi(n); for (int i = 1; i < n; ++i) { int u, v; gii(u, v); edge[u].pb(v); edge[v].pb(u); } scanf("%s", str + 1); for (int i = 1; i <= n; ++i) str[i] -= ‘0‘; for (int i = 1; i <= n; ++i) if (!str[i]) num[i] = N; int root = 1; for (; !str[root]; ++root); dfs1(root); for (int i = 1; i <= n; ++i) d[in[i]] = dep[i]; build(1, 1, n); dfs2(root); dfs3(root); printf("%lld ", ans + mxt[root]); return 0; }
以上是关于AtCoder Grand Contest 008 题解的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Grand Contest 008 D - K-th K
markdown AtCoder Grand Contest 016