Atcoder Grand Contest 006 题解
A - Prefix and Suffix
模拟。
//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; } char s[110], t[110]; int N; int main() { gi(N); scanf("%s", s + 1); scanf("%s", t + 1); for (int i = N; i; --i) { int flag = 1; for (int j = 1; j <= i; ++j) if (s[N - i + j] != t[j]) flag = 0; if (flag) { printf("%d\n", N + N - i); return 0; } } printf("%d\n", N + N); return 0; }
B - Median Pyramid Easy
在n和n+1处构造出两个相同的肯定会一直传递到顶。
//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 ans[200010], vis[200010]; int main() { int n, x; gii(n, x); if (n == 2) { if (x == 2) { printf("Yes\n1\n2\n3\n"); return 0; } puts("No"); return 0; } int round = n; n <<= 1; --n; int A = n - x, B = x - 1; if (B >= 1 && A >= 2) { ans[round] = x; ans[round + 1] = x - 1; ans[round - 1] = x + 1; ans[round + 2] = x + 2; vis[x] = vis[x + 1] = vis[x - 1] = vis[x + 2] = 1; int t = 0; for (int i = 1; i <= n; ++i) { while (ans[t + 1]) ++t; if (!vis[i]) ans[++t] = i; } puts("Yes"); for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]); return 0; } else if (B >= 2 && A >= 1) { ans[round] = x; ans[round + 1] = x + 1; ans[round - 1] = x - 1; ans[round + 2] = x - 2; vis[x] = vis[x + 1] = vis[x - 1] = vis[x - 2] = 1; int t = 0; for (int i = 1; i <= n; ++i) { while (ans[t + 1]) ++t; if (!vis[i]) ans[++t] = i; } puts("Yes"); for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]); return 0; } puts("No"); return 0; }
C - Rabbit Exercise
跳一次就相当于差分数组两个位置交换一下,这是个排列的置换,可以快速幂优化。
//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 = 100010; void mul(int *a, int *b, int n) { static int t[N], h[N]; for (int i = 1; i <= n; ++i) t[i] = a[i], h[i] = b[i]; for (int i = 1; i <= n; ++i) a[i] = t[h[i]]; } void fpow(int *a, int n, long long k) { static int t[N]; for (int i = 1; i <= n; ++i) t[i] = i; for (; k; k >>= 1) { if (k & 1) mul(t, a, n); mul(a, a, n); } for (int i = 1; i <= n; ++i) a[i] = t[i]; } int n; long long x[N]; int m, a[N]; long long k; int main() { gi(n); for (int i = 1; i <= n; ++i) gi(x[i]), a[i] = i; for (int i = n; i; --i) x[i] -= x[i - 1]; gi(m); scanf("%lld", &k); for (int i = 1; i <= m; ++i) { int p; gi(p); swap(a[p], a[p + 1]); } fpow(a, n, k); for (int i = 1; i <= n; ++i) { //cerr << a[i] << " : " << x[a[i]] << endl; x[a[i]] += x[a[i - 1]]; printf("%lld\n", x[a[i]]); } return 0; }
D - Median Pyramid Hard
二分答案,01抵消掉,最近的连续的就是答案。
//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; int n, a[N]; bool check(int mid) { for (int i = 1; i <= n - 1; ++i) { if ((a[n + i - 1] >= mid) == (a[n + i] >= mid)) return a[n + i] >= mid; if ((a[n - i + 1] >= mid) == (a[n - i] >= mid)) return a[n - i] >= mid; } return a[1] >= mid; } int main() { gi(n); for (int i = 1; i <= 2 * n - 1; ++i) gi(a[i]); int x = 1, v = 2 * n - 1; for (int i = 19; ~i; --i) if (x + (1 << i) <= v && check(x + (1 << i))) x += 1 << i; printf("%d\n", x); }
E - Rotate 3x3
首先一列本质就是一个数字带有正反。
算一下移动次数和翻转次数的奇偶性判断一下即可。
//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 = 1e5 + 10;; int a[3][N], n, s[N], d[N], p[N], cnt[2], ds[2]; int tree[N]; void change(int x) { for (; x; x -= x & -x) ++tree[x]; } int query(int x) { int v = 0; for (; x <= n; x += x & -x) v += tree[x]; return v; } int main() { gi(n); for (int j = 0; j < 3; ++j) for (int i = 1; i <= n; ++i) gi(a[j][i]); for (int i = 1; i <= n; ++i) { if (a[0][i] == a[1][i] + 1 && a[1][i] == a[2][i] + 1) s[i] = a[0][i] / 3, d[i] = 1; else if (a[0][i] == a[1][i] - 1 && a[1][i] == a[2][i] - 1) s[i] = a[2][i] / 3, d[i] = 0; else return puts("No"), 0; if ((s[i] & 1) != (i & 1)) return puts("No"), 0; cnt[i & 1] += d[i]; } for (int i = 1; i <= n; ++i) p[s[i]] = i; for (int i = 1; i <= n; i += 2) { int now = p[i] + (query(p[i]) << 1); ds[1] += (abs(now - i) >> 1) & 1; change(p[i]); } memset(tree, 0, sizeof tree); for (int i = 2; i <= n; i += 2) { int now = p[i] + (query(p[i]) << 1); ds[0] += (abs(now - i) >> 1) & 1; change(p[i]); } if ((cnt[0] & 1) != (ds[1] & 1) || (cnt[1] & 1) != (ds[0] & 1)) return puts("No"), 0; puts("Yes"); return 0; }
F - Blackout
本质是一个有向图问题,我们将图染成三种颜色做一下就好了。
//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 = 1e5 + 10; int n, m; vector<int> e1[N], e2[N]; bool vis[N]; int co[N], flag, cnt[3], s, e; void dfs(int u) { vis[u] = 1; ++s; ++cnt[co[u]]; for (auto v : e1[u]) { ++e; if (vis[v]) { if (co[v] != (co[u] + 1) % 3) flag = 0; continue; } co[v] = (co[u] + 1) % 3; dfs(v); } for (auto v : e2[u]) { if (vis[v]) { if (co[v] != (co[u] + 2) % 3) flag = 0; continue; } co[v] = (co[u] + 2) % 3; dfs(v); } } long long ans; int main() { gii(n, m); for (int i = 1; i <= m; ++i) { int u, v; gii(u, v); e1[u].pb(v); e2[v].pb(u); } for (int i = 1; i <= n; ++i) { if (!vis[i]) { e = 0; s = 0; flag = 1; cnt[0] = cnt[1] = cnt[2] = 0; dfs(i); if (!flag) { ans += 1LL * s * s; } else if (cnt[0] && cnt[1] && cnt[2]) { ans += 1LL * cnt[0] * cnt[1] + 1LL * cnt[1] * cnt[2] + 1LL * cnt[0] * cnt[2]; } else ans += e; } } printf("%lld\n", ans); return 0; }