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 \texttt{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) f_k(x)表示 k k層的子樹的 prufer \texttt{prufer}序列和, f(x)=ax+bx2+c f(x) = ax + b\frac{x}{2} + c,然後就可以遞推了。
詢問的時候記憶化搜尋,將 k 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[n][a] == tim) return f[n][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[n][a] = tim, f[n][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)