CodeForces Gym 101620简要题解
2017-12-15 14:06
645 查看
Assignment Algorithm
模拟。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 55; char a[MAXN][MAXN]; int n, m; inline void Solve(char c) { vector <pii> row; int cnt_1 = 0, cnt_2 = 0, t = 1, l = 0, r = 0; for (int j = 0; j < 11; j ++) cnt_1 += a[1][j] == '-', cnt_2 += a[n / 2 + 2][j] == '-'; if (cnt_1 || cnt_2) { if (cnt_1) row.pb(mp(cnt_1, 1)); if (cnt_2) row.pb(mp(cnt_2, n / 2 + 2)); } else { for (int i = 0; i < n + 3; i ++) { int cnt = 0; for (int j = 0; j < 11; j ++) cnt += a[i][j] == '-'; if (cnt) row.pb(mp(cnt, i)); } } sort(row.begin(), row.end(), greater <pii> ()); for (int i = 1; i < row.size(); i ++) if (row[i].xx == row[0].xx) t = i + 1; for (int i = 0; i < t; i ++) row[i].xx = min(min(row[i].yy, n + 2 - row[i].yy), abs(row[i].yy - (n / 2 + 1))); sort(row.begin(), row.begin() + t); for (int i = 0; i < n + 3; i ++) { for (int j = 0; j < 5; j ++) l += a[i][j] == '-'; for (int j = 6; j < 11; j ++) r += a[i][j] == '-'; } int idx = row[0].yy; if (a[idx][4] == '-' || a[idx][6] == '-') { if (a[idx][4] != '-') a[idx][6] = c; else if (a[idx][6] != '-') a[idx][4] = c; else if (l >= r) a[idx][4] = c; else a[idx][6] = c; } else if (a[idx][2] == '-' || a[idx][8] == '-') { if (a[idx][2] != '-') a[idx][8] = c; else if (a[idx][8] != '-') a[idx][2] = c; else if (l >= r) a[idx][2] = c; else a[idx][8] = c; } else if (a[idx][0] == '-' || a[idx][10] == '-') { if (a[idx][0] != '-') a[idx][10] = c; else if (a[idx][10] != '-') a[idx][0] = c; else if (l >= r) a[idx][0] = c; else a[idx][10] = c; } else if (a[idx][5] == '-') { a[idx][5] = c; } else { if (a[idx][1] != '-') a[idx][9] = c; else if (a[idx][9] != '-') a[idx][1] = c; else if (l >= r) a[idx][1] = c; else a[idx][9] = c; } } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), m = Read(); for (int i = 0; i < n + 3; i ++) scanf("%s", a[i]); for (int i = 0; i < m; i ++) Solve(i + 'a'); for (int i = 0; i < n + 3; i ++, putchar(10)) for (int j = 0; j < 11; j ++) putchar(a[i][j]); return 0; }
Buffalo Barricades
从上到下扫描线,用set维护当前的情况,并记录每个点的父亲,最后并查集扫一遍维护。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 300005; struct Event { int typ, x, y, i; bool operator < (const Event &b) const { return y > b.y || (y == b.y && typ > b.typ); } } a[MAXN << 1]; int n, m, f[MAXN], tmp[MAXN], tag[MAXN], ans[MAXN], par[MAXN]; set <pii> s; inline int Find(int x) { while (x ^ f[x]) x = f[x] = f[f[x]]; return x; } inline void Merge(int x, int y) { if (x ^ y) f[x] = y, tag[y] += tag[x]; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(); for (int i = 1; i <= n; i ++) a[i].x = Read(), a[i].y = Read(), a[i].i = i, a[i].typ = 1; m = Read(); for (int i = n + 1; i <= n + m; i ++) a[i].x = Read(), a[i].y = Read(), a[i].i = i - n, a[i].typ = 2; sort(a + 1, a + n + m + 1); for (int i = 1; i <= n + m; i ++) if (a[i].typ == 1) { auto it = s.lower_bound(mp(a[i].x, -1)); if (it != s.end()) tmp[it -> yy] ++; } else { auto it = s.insert(mp(a[i].x, a[i].i)).xx, jt = it; if (jt != -- s.end()) par[a[i].i] = (++ jt) -> yy; while (it != s.begin()) { jt = it, jt --; if (jt -> yy > a[i].i) s.erase(jt); else break; } } for (int i = 1; i <= m; i ++) f[i] = i; for (int i = m; i; i --) ans[i] = tag[Find(i)] += tmp[i], Merge(Find(i), Find(par[i])); for (int i = 1; i <= m; i ++) printf("%d\n", ans[i]); return 0; }
Cumulative Code
记fk(x)表示k层的子树的prufer序列和,f(x)=ax+bx2+c,然后就可以递推了。询问的时候记忆化搜索,将k层及以下的情况记下来,注意一些边界情况。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 32780; struct Node { LL a, b, c; Node(LL a = 0, LL b = 0, LL c = 0):a(a), b(b), c(c) {} Node operator + (const Node &d) const { return Node(a + 2 * d.a + d.b, b, c + d.c); }; Node operator - (const Node &d) const { return Node(a + 2 * d.a + d.b, b, c + d.c + d.a); } } f[16][MAXN]; int tim, vis[16][MAXN]; inline Node Solve(int n, int a, int d, int m, bool p) { if (n == 1) return Node(0, 1, 0); bool mem = n <= 15 && a + d * m >= (1 << n) - 1 && p; if (mem && vis [a] == tim) return f [a]; Node ret(0, 0, 0); int cur = a; if (cur < (1 << n - 1) - 1 && m) { int t = min(m, ((1 << n - 1) - 1 - cur - 1) / d + 1); ret = ret + Solve(n - 1, cur, d, t, true), cur += t * d, m -= t; } cur -= (1 << n - 1) - 1; if (!p) { if (!cur && m) m --, cur += d, ret.a += 2, ret.c ++; cur --; } if (cur < (1 << n - 1) - 1 && m) { int t = min(m, ((1 << n - 1) - 1 - cur - 1) / d + 1); ret = ret - Solve(n - 1, cur, d, t, p), cur += t * d, m -= t; } cur -= (1 << n - 1) - 1; if (p && m) ret.b ++; if (mem) vis [a] = tim, f [a] = ret; return ret; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif int n = Read(), q = Read(); while (q --) { int a = Read() - 1, d = Read(), m = Read(); tim ++; Node ret = Solve(n, a, d, m, false); printf("%lld\n", ret.a + ret.c); } return 0; }
Donut Drone
将(x,0)跳c次的情况记下来,询问可以暴力。考虑修改,倒着推回去,不难发现最后一定是一段区间被影响了,也可以暴力维护。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 2005; int n, m, q, tim, cur_x, cur_y, vis[MAXN], lst[MAXN], nxt[MAXN], a[MAXN][MAXN]; inline int R(int x) { x %= n; return x < 0 ? x + n : x; } inline int C(int x) { x %= m; return x < 0 ? x + m : x; } inline int FindNext(int x, int y) { int val = -1, ret = -1; for (int i = x - 1; i <= x + 1; i ++) if (val < a[R(i)][C(y + 1)]) ret = i, val = a[R(i)][C(y + 1)]; return ret; } inline int Jump(int x, int y) { for (; y < m; x = R(FindNext(x, y ++))); return x; } inline int Move(int t) { if (t >= m - cur_y) while (cur_y) cur_x = R(FindNext(cur_x, cur_y)), cur_y = C(cur_y + 1), t --; tim ++; while (t >= m) { t -= m, cur_x = nxt[cur_x]; if (vis[cur_x] == tim) t %= lst[cur_x] - t; vis[cur_x] = tim, lst[cur_x] = t; } while (t) cur_x = R(FindNext(cur_x, cur_y)), cur_y = C(cur_y + 1), t --; } inline void Modify(int x, int y) { int pos = Jump(x, y); pii cur = mp(x, x); while (y) { y --; pii nxt = mp(INT_MAX, INT_MIN); for (int i = cur.xx + 1; i >= cur.xx - 1; i --) { int p = FindNext(i, y); if (p >= cur.xx && p <= cur.yy) nxt.xx = i; } for (int i = cur.yy - 1; i <= cur.yy + 1; i ++) { int p = FindNext(i, y); if (p >= cur.xx && p <= cur.yy) nxt.yy = i; } if (nxt.xx > nxt.yy) return ; cur = nxt; } if (cur.yy - cur.xx >= n) for (int i = 0; i < n; i ++) nxt[i] = pos; else for (int i = cur.xx; i <= cur.yy; i ++) nxt[R(i)] = pos; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), m = Read(); for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) a[i][j] = Read(); for (int i = 0; i < n; i ++) nxt[i] = Jump(i, 0); q = Read(); while (q --) { char opt[10]; scanf("%s", opt); if (opt[0] == 'm') Move(Read()), printf("%d %d\n", cur_x + 1, cur_y + 1); else { int x = Read() - 1, y = Read() - 1; a[x][y] = Read(); for (int i = x - 1; i <= x + 1; i ++) Modify(R(i), C(y - 1)); } } return 0; }
Embedding Enumeration
首先必须是一棵二叉树,不然无解。暴力做法可以f(i,j)表示当前还剩i的子树没有放,并且已经放的长的一行减去短的一行长度为j。
事实上j大多数时候是1,而不是1的时候也可以比较方便地特判掉。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 300005; const int mod = 1e9 + 7; int n, ans, deg[MAXN], par[MAXN], nxt[MAXN], dis[MAXN], adj[MAXN][3], f[MAXN][4][4]; vector <int> seq; inline void Addedge(int x, int y) { if (deg[x] == 3 || deg[y] == 3) puts("0"), exit(0); adj[x][deg[x] ++] = y, adj[y][deg[y] ++] = x; } inline void DFS(int x) { seq.pb(x); for (int i = 0; i < deg[x]; i ++) if (adj[x][i] ^ par[x]) par[adj[x][i]] = x, DFS(adj[x][i]); } inline bool Find(int x, int y, int z, int &r) { bool flg = false; r = -1; for (int i = 0; i < deg[x]; i ++) if ((adj[x][i] ^ y) && (adj[x][i] ^ z)) { if (flg) return false; flg = true, r = adj[x][i]; } return true; } inline bool Chain(int x) { return deg[nxt[x]] == 1; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), Addedge(0, 1); for (int i = 1; i < n; i ++) Addedge(Read(), Read()); par[0] = -1, DFS(0); for (int i = n; i; i --) { int x = seq[i], y; if (deg[x] == 2) Find(x, par[x], -1, y), nxt[x] = nxt[y], dis[x] = dis[y] + 1; else nxt[x] = x, dis[x] = 0; } f[0][1][0] = 1; for (auto x : seq) for (int i = 0; i <= deg[x]; i ++) for (int j = 0, y = i == deg[x] ? n + 1 : adj[x][i], z, u, v; j <= deg[y]; j ++) if (f[x][i][j]) if (Find(x, par[x], y, u) && Find(y, x, z = j == deg[y] ? n + 1 : adj[y][j], v)) { if (~u && ~v) { while (deg[u] == 2 && deg[v] == 2) Find(u, par[u], -1, u), Find(v, par[v], -1, v); if (!Find(u, par[u], -1, u) || !Find(v, par[v], -1, v)) continue; } if (!~u && !~v) ans = (ans + f[x][i][j]) % mod; else { if (~v) swap(u, v); f[u][deg[u]][0] = (f[u][deg[u]][0] + f[x][i][j]) % mod; for (int k = 0; k < deg[u]; k ++) if (adj[u][k] ^ par[u]) f[u][k][deg[adj[u][k]]] = (f[u][k][deg[adj[u][k]]] + f[x][i][j]) % mod; if (Chain(u)) { if (dis[u] >= 3 && (dis[u] & 1)) ans = (ans + f[x][i][j]) % mod; } else for (int t = 0, p = nxt[u], q, r; t < 2; t ++, p = par[p]) for (int k = 0; k < deg[p]; k ++) if ((q = adj[p][k]) ^ par[p]) for (int l = 0; l < deg[q]; l ++) if ((r = adj[q][l]) ^ p) if (Chain(r) && dis[r] + 1 == dis[u] - t) f[p][k][l] = (f[p][k][l] + f[x][i][j]) % mod; } } return printf("%d\n", ans), 0; }
Faulty Factorial
分类讨论。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline LL Read() { LL x = 0; int f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } LL n; int p, r; inline int Qow(int x, int y) { int r = 1; for (; y; y >>= 1, x = 1LL * x * x % p) if (y & 1) r = 1LL * r * x % p; return r; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), p = Read(), r = Read(); if (!r) { if (n <= 2 || n < p) return puts("-1 -1"), 0; return printf("%d 1\n", 2 + (p == 2)), 0; } if (n >= p * 2) return puts("-1 -1"), 0; int fac = 1; for (int i = 1; i <= n; i ++) if (i ^ p) fac = 1LL * fac * i % p; int inv = Qow(fac, p - 2); if (n >= p) return printf("%d %d\n", p, 1LL * inv * r % p), 0; for (int i = 2; i <= n; i ++) { int v = 1LL * inv * i % p * r % p; if (v < i) return printf("%d %d\n", i, v), 0; } return puts("-1 -1"), 0; }
Gambling Guide
记f(x)表示x走到n的期望步数,那么显然f(y)<f(x)才会移动。类似Dijkstra维护转移。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 300005; priority_queue <pair <double, int>> q; double f[MAXN], sum[MAXN]; vector <int> adj[MAXN]; int n, m, cnt[MAXN]; bool vis[MAXN]; int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), m = Read(); for (int i = 1, x, y; i <= m; i ++) x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x); f = 0, q.push(mp(0, n)); for (int i = 1; i <= n; i ++) sum[i] = adj[i].size(); while (!q.empty()) { int x = q.top().yy; q.pop(); if (vis[x]) continue; vis[x] = true; for (auto y : adj[x]) if (!vis[y]) cnt[y] ++, sum[y] += f[x], f[y] = sum[y] / cnt[y], q.push(mp(-f[y], y)); } return printf("%lf\n", f[1]), 0; }
Hidden Hierarchy
模拟。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 100005; int n, cnt, lim, siz[MAXN]; set <string> chd[MAXN]; vector <int> adj[MAXN]; map <int, string> rel; map <string, int> idx; bool fil[MAXN]; inline void DFS(int x) { for (auto y : adj[x]) DFS(y), siz[x] += siz[y]; } inline void Solve(int x) { if (fil[x]) return ; bool flg = false; int val = 0; for (auto y : adj[x]) if (!fil[y]) val = max(val, siz[y]), flg = true; if (!flg) { cout << " " << rel[x] << " " << siz[x] << endl; return ; } if (val >= lim) { cout << "- " << rel[x] << " " << siz[x] << endl; for (auto c : chd[x]) Solve(idx[c]); return ; } else { cout << "+ " << rel[x] << " " << siz[x] << endl; return ; } } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(); for (int i = 1; i <= n; i ++) { string str, pre; cin >> str; idx[str] = ++ cnt, rel[cnt] = str, siz[cnt] = Read(), pre = str, fil[cnt] = true; for (int i = str.length() - 1; ~i; i --) if (str[i] == '/') { string cur = str.substr(0, i + 1); if (idx.find(cur) == idx.end()) { idx[cur] = ++ cnt, rel[cnt] = cur; adj[cnt].pb(cnt - 1), chd[cnt].insert(pre), pre = cur; } else { adj[idx[cur]].pb(cnt), chd[idx[cur]].insert(pre); break; } } } lim = Read(), DFS(idx["/"]), Solve(idx["/"]); return 0; }
Intrinsic Interval
考虑一对相邻的数(pi,pi+1),如果它们选了那么它们之间的数也必须选,求出值域在它们之间的出现位置[l,r],那么让i向[l,r)所有点连边。不难发现最后答案就是这个区间所有点可达点的最小标号和最大标号。
用线段树优化建边和维护查询。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 500005; int n, m, ql, qr, cnt, tot, tim, top, seg_rot, d[MAXN], p[MAXN], q[MAXN], dfn[MAXN], low[MAXN], scc[MAXN], lch[MAXN], rch[MAXN], sta[MAXN], adj_min[MAXN], adj_max[MAXN], seg_min[MAXN], seg_max[MAXN]; vector <int> adj[MAXN], adv[MAXN]; inline void Modify(int x, int l, int r, int p, int u, int v) { seg_min[x] = min(seg_min[x], u), seg_max[x] = max(seg_max[x], v); if (l == r) return ; int mid = l + r >> 1; return p <= mid ? Modify(x << 1, l, mid, p, u, v) : Modify(x << 1 | 1, mid + 1, r, p, u, v); } inline pii Query(int x, int l, int r, int ql, int qr) { if (l == ql && r == qr) return mp(seg_min[x], seg_max[x]); int mid = l + r >> 1; if (qr <= mid) return Query(x << 1, l, mid, ql, qr); if (ql > mid) return Query(x << 1 | 1, mid + 1, r, ql, qr); pii L = Query(x << 1, l, mid, ql, mid), R = Query(x << 1 | 1, mid + 1, r, mid + 1, qr); return mp(min(L.xx, R.xx), max(L.yy, R.yy)); } inline void Build(int &x, int l, int r) { x = ++ tot; if (l == r) return (void)(adj[x].pb(l)); int mid = l + r >> 1; Build(lch[x], l, mid), Build(rch[x], mid + 1, r), adj[x].pb(lch[x]), adj[x].pb(rch[x]); } inline void Addedge(int x, int l, int r, int ql, int qr, int p) { if (l == ql && r == qr) return (void)(adj[p].pb(x)); int mid = l + r >> 1; if (qr <= mid) Addedge(lch[x], l, mid, ql, qr, p); else if (ql > mid) Addedge(rch[x], mid + 1, r, ql, qr, p); else Addedge(lch[x], l, mid, ql, mid, p), Addedge(rch[x], mid + 1, r, mid + 1, qr, p); } inline void DFS(int x) { dfn[x] = low[x] = ++ tim, sta[++ top] = x; for (auto y : adj[x]) if (!dfn[y]) DFS(y), low[x] = min(low[x], low[y]); else if (!scc[y]) low[x] = min(low[x], dfn[y]); if (dfn[x] == low[x]) { cnt ++, adj_min[cnt] = n, adj_max[cnt] = 0; for (int k = 0; k ^ x; ) { scc[k = sta[top --]] = cnt; if (k < n) adj_min[cnt] = min(adj_min[cnt], k), adj_max[cnt] = max(adj_max[cnt], k); } } } inline void ReBuild() { for (int i = 1; i <= tot; i ++) for (auto j : adj[i]) if (scc[i] ^ scc[j]) adv[scc[i]].pb(scc[j]), d[scc[j]] ++; for (int i = 1; i <= cnt; i ++) if (!d[i]) q[++ qr] = i; while (ql < qr) { int x = q[++ ql]; for (auto y : adv[x]) if (!-- d[y]) q[++ qr] = y; } for (int i = qr; i; i --) { int x = q[i]; for (auto y : adv[x]) adj_min[x] = min(adj_min[x], adj_min[y]), adj_max[x] = max(adj_max[x], adj_max[y]); } } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(), tot = n - 1; mset(seg_min, 0x3f), mset(seg_max, 0); for (int i = 1; i <= n; i ++) p[i] = Read(), Modify(1, 1, n, p[i], i, i); if (n == 1) { m = Read(); while (m --) puts("1 1"); return 0; } Build(seg_rot, 1, n - 1); for (int i = 1; i < n; i ++) { int l = p[i], r = p[i + 1]; if (l > r) swap(l, r); pii ret = Query(1, 1, n, l, r); Addedge(seg_rot, 1, n - 1, ret.xx, ret.yy - 1, i); } for (int i = 1; i <= tot; i ++) if (!dfn[i]) DFS(i); ReBuild(); mset(seg_min, 0x3f), mset(seg_max, 0); for (int i = 1; i < n; i ++) Modify(1, 1, n - 1, i, adj_min[scc[i]], adj_max[scc[i]]); m = Read(); while (m --) { int l = Read(), r = Read(); if (l == r) printf("%d %d\n", l, r); else { pii ret = Query(1, 1, n - 1, l, r - 1); printf("%d %d\n", ret.xx, ret.yy + 1); } } return 0; }
Justified Jungle
暴力。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 1000005; int n, siz[MAXN], cnt[MAXN]; vector <int> fac, ans, adj[MAXN]; inline void DFS(int x, int p) { siz[x] = 1; for (auto y : adj[x]) if (y ^ p) DFS(y, x), siz[x] += siz[y]; if (x ^ 1) cnt[__gcd(siz[x], n)] ++; } int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(); for (int i = 1; i < n; i ++) if (n % i == 0) fac.pb(i); for (int i = 1, x, y; i < n; i ++) x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x); DFS(1, 0); for (int i = 0; i < fac.size(); i ++) for (int j = i + 1; j < fac.size(); j ++) if (fac[j] % fac[i] == 0) cnt[fac[i]] += cnt[fac[j]]; for (auto x : fac) if (cnt[x] == n / x - 1) ans.pb(n / x - 1); reverse(ans.begin(), ans.end()); for (auto x : ans) printf("%d ", x); putchar(10); return 0; }
Kitchen Knobs
首先去掉所有位置都是相同数字的,然后差分,每次操作相当于某个位置加x,另一个位置减x。不难转化成:将所有数分成尽量多组,满足每组和为0,答案是n减去组数。
贪心之后只有三种数了,暴力DP即可。
#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 505; int n, b[MAXN], cnt[7], f[MAXN][MAXN][7], g[MAXN][MAXN][7]; int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(); for (int i = 1; i <= n; i ++) { int a[7]; a[0] = Read(); for (int j = 1; j < 7; j ++) a[j] = a[j - 1] / 10 + a[j - 1] % 10 * 1000000; if (a[0] == a[1]) i --, n --; else b[i] = max_element(a, a + 7) - a; } for (int i = 1; i <= n + 1; i ++) cnt[(b[i] - b[i - 1] + 7) % 7] ++; int ret = n + 1 - cnt[0]; for (int i = 1, v; i < 4; i ++) v = min(cnt[i], cnt[7 - i]), ret -= v, cnt[i] -= v, cnt[7 - i] -= v; int x = cnt[1] ? 1 : 6, cx = cnt[1] ? cnt[1] : cnt[6], y = cnt[2] ? 2 : 5, cy = cnt[2] ? cnt[2] : cnt[5], z = cnt[3] ? 3 : 4, cz = cnt[3] ? cnt[3] : cnt[4]; for (int i = 0; i <= cy; i ++) for (int j = 0; j <= cz; j ++) for (int k = 0; k < 7; k ++) f[i][j][k] = -1; f[0][0][0] = 0; for (int l = 0; l <= cx; l ++) { for (int i = 0; i <= cy; i ++) for (int j = 0; j <= cz; j ++) for (int k = 0; k < 7; k ++) g[i][j][k] = f[i][j][k], f[i][j][k] = -1; for (int i = 0; i <= cy; i ++) for (int j = 0; j <= cz; j ++) for (int k = 0; k < 7; k ++) if (~g[i][j][k]) { if (l < cx) f[i][j][(k + x) % 7] = max(f[i][j][(k + x) % 7], g[i][j][k] + ((k + x) % 7 == 0)); if (i < cy) g[i + 1][j][(k + y) % 7] = max(g[i + 1][j][(k + y) % 7], g[i][j][k] + ((k + y) % 7 == 0)); if (j < cz) g[i][j + 1][(k + z) % 7] = max(g[i][j + 1][(k + z) % 7], g[i][j][k] + ((k + z) % 7 == 0)); } } return printf("%d\n", ret - g[cy][cz][0]), 0; }
Lunar Landscape
前缀和。#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define mset(x, y) memset(x, y, sizeof x) #define mcpy(x, y) memcpy(x, y, sizeof x) using namespace std; typedef long long LL; typedef pair <int, int> pii; inline int Read() { int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; } const int MAXN = 3005; const int N = 3002; int n, a[MAXN][MAXN], b[MAXN][MAXN]; double ans; int main() { #ifdef wxh010910 freopen("data.in", "r", stdin); #endif n = Read(); for (int i = 1; i <= n; i ++) { char opt[2]; scanf("%s", opt); int x = Read(), y = Read(), z = Read(); if (opt[0] == 'A') x += N / 2 - z / 2, y += N / 2 - z / 2, a[x][y] = max(a[x][y], z); else x += N / 2 - z / 2, y += N / 2, b[x][y] = max(b[x][y], z); } for (int i = 1; i <= N; i ++) for (int j = 1; j <= N; j ++) a[i][j] = max(max(a[i][j], a[i - 1][j - 1] - 1), max(a[i - 1][j] - 1, a[i][j - 1] - 1)), b[i][j] = max(max(b[i][j], b[i - 1][j] - 1), max(b[i - 1][j - 1] - 2, b[i - 1][j + 1] - 2)); for (int i = 1; i <= N; i ++) for (int j = 1; j <= N; j ++) if (a[i][j]) ans ++; else { if (b[i][j]) ans += 0.25; if (b[i][j + 1]) ans += 0.25; if (b[i][j] > 1 || b[i][j + 1] > 1) ans += 0.25; if (b[i - 1][j] > 1 || b[i - 1][j + 1] > 1) ans += 0.25; } return printf("%.2lf\n", ans), 0; }
相关文章推荐
- [Codeforces Gym]2015年ACM-ICPC越南国赛第二场简要题解
- CodeForces Gym 101190简要题解
- CodeForces Gym 101630简要题解
- CodeForces Gym 101745 简要题解
- CodeForces Gym 101615简要题解
- CodeForces Gym 101741 简要题解
- Codeforces Gym 100269D Dwarf Tower spfa
- Codeforces Gym 101158 E. Infallibly Crack Perplexing Cryptarithm (模拟 + 语法分析)
- Codeforces Gym 101174 E. Passwords (AC 自动机 + DP)
- codeforces Gym - 101485 A (2015-2016 Northwestern European Regional Contest (NWERC 2015))
- Codeforces Gym 100825 B. Delete This! (枚举 + 三分)
- Codeforces Gym 101064E A Word to Trump All [AC自动机+bfs]
- codeforces Gym - 101190F——Foreign Postcards(动态规划)
- Codeforces Gym 100269E Energy Tycoon 贪心
- 【宽搜】ECNA 2015 D Rings (Codeforces GYM 100825)
- Codeforces GYM 100340A Cookies
- codeforces gym-101755 I-Guess the Tree 交互题、分治、树的直径
- Codeforces Gym 100500A Poetry Challenge (博弈论基础题)
- [博弈论] Codeforces Gym 101190 NEERC 16 G. Game on Graph
- [杂题 交互] Codeforces Gym 101190 NEERC 16 I. Indiana Jones and the Uniform Cave