[Template]省选复习计划
2017-04-17 22:44
218 查看
[Template]省选复习计划
字符串相关
KMP算法(luogu3375)
7′40′′#include <bits/stdc++.h> using namespace std; const int MAXN = 1000005, MAXM = 1005; char s1[MAXN], s2[MAXM]; int pi[MAXM]; void kmp_init(int len) { pi[0] = pi[1] = 0; int j = 0; for (int i = 2; i <= len; i++) { while (j && s2[j+1] != s2[i]) j = pi[j]; if (s2[j+1] == s2[i]) j++; pi[i] = j; } } void kmp_match(int len) { int j = 0, p = strlen(s2+1); for (int i = 1; i <= len; i++) { while (j && s1[i] != s2[j+1]) j = pi[j]; if (s1[i] == s2[j+1]) ++j; if (j == p) printf("%d\n", i-p+1), j = pi[j]; } } int main() { scanf("%s", s1+1), scanf("%s", s2+1); kmp_init(strlen(s2+1)); kmp_match(strlen(s1+1)); for (int i = 1, l = strlen(s2+1); i <= l; i++) printf("%d ", pi[i]); return 0; }
AC自动机(hdu2222)
32′42′′#include <bits/stdc++.h> using namespace std; const int MAXN = 1000005; int chl[MAXN][26], fail[MAXN], fin[MAXN], top = 0, root = 0, mak[MAXN]; void push(int &nd, char *str) { if (!nd) nd = ++top; if (*str == '\0') fin[nd]++; else push(chl[nd][*str-'a'], str+1); } struct node { int to, next; } edge[MAXN]; int head[MAXN], tp = 0; void push(int i, int j) { ++tp, edge[tp] = (node) {j, head[i]}, head[i] = tp; } queue<int> que; void init() { fail[root] = 0, que.push(root); while (!que.empty()) { int tp = que.front(); que.pop(); for (int i = 0; i < 26; i++) { if (!chl[tp][i]) continue; int p = fail[tp]; while (p && !chl[p][i]) p = fail[p]; if (p) fail[chl[tp][i]] = chl[p][i]; else fail[chl[tp][i]] = root; push(fail[chl[tp][i]], chl[tp][i]); que.push(chl[tp][i]); } } } void match(int nd, char *str) { if (fin[nd]) mak[nd] = 1; if (*str == '\0') return; while (nd && !chl[nd][*str-'a']) nd = fail[nd]; if (nd) match(chl[nd][*str-'a'], str+1); else match(root, str+1); } int dp[MAXN], siz[MAXN]; // 两次collect int dfs1(int nd) { if (!nd) return 0; if (siz[nd] != -1) return siz[nd]; for (int i = 0; i < 26; i++) mak[nd] |= dfs1(chl[nd][i]); return siz[nd] = mak[nd]; } int dfs2(int nd) { if (dp[nd] != -1) return dp[nd]; dp[nd] = siz[nd]; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; dp[nd] |= dfs2(to); } return dp[nd]; } char str[MAXN]; int T, n; void clear() { top = root = tp = 0, memset(chl, 0, sizeof chl), memset(fail, 0, sizeof fail); memset(fin, 0, sizeof fin), memset(mak, 0, sizeof mak); memset(siz, -1, sizeof siz), memset(dp, -1, sizeof dp); memset(head, 0, sizeof head); } int main() { scanf("%d", &T); while (T--) { clear(); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", str); push(root, str); } init(); scanf("%s", str); match(root, str); dfs1(root), dfs2(root); int ans = 0; for (int i = 1; i <= top; i++) ans += dfs2(i)*fin[i]; printf("%d\n", ans); } return 0; }
SA
24′′04′,然而参考了模板…第二次14′15′′
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5+5, N = 1e5; struct ele { int k[2], id; ele(){} ele(int a, int b, int c) { k[0] = a, k[1] = b, id = c; } } RE[MAXN], RT[MAXN]; int sa[MAXN], rk[MAXN], height[MAXN], sum[MAXN], n; char str[MAXN]; void radix_sort() { for (int y = 1; y >= 0; y--) { memset(sum, 0, sizeof sum); for (int i = 1; i <= n; i++) sum[RE[i].k[y]]++; for (int i = 1; i <= N; i++) sum[i] += sum[i-1]; for (int i = n; i >= 1; i--) RT[sum[RE[i].k[y]]--] = RE[i]; for (int i = 1; i <= n; i++) RE[i] = RT[i]; } for (int i = 1; i <= n; i++) { rk[RE[i].id] = rk[RE[i-1].id]; if (RE[i].k[0] != RE[i-1].k[0] || RE[i].k[1] != RE[i-1].k[1]) rk[RE[i].id]++; } } void calc_sa() { for (int i = 1; i <= n; i++) RE[i] = ele(str[i]-'a'+1, 0, i); radix_sort(); for (int k = 1; k < n; k <<= 1) { for (int i = 1; i <= n; i++) RE[i] = ele(rk[i], i+k<=n?rk[i+k]:0, i); radix_sort(); } for (int i = 1; i <= n; i++) sa[rk[i]] = i; } void calc_height() { int h = 0; for (int i = 1; i <= n; i++) { if (rk[i] == 1) h = 0; else { int k = sa[rk[i]-1]; if (--h < 0) h = 0; while (str[i+h] == str[k+h]) h++; } height[rk[i]] = h; } } int main() { scanf("%s", str+1); n = strlen(str+1); calc_sa(), calc_height(); for (int i = 1; i <= n; i++) printf("%d ", sa[i]); puts(""); for (int i = 2; i <= n; i++) printf("%d ", height[i]); return 0; }
SAM
luogu28528′59′′
#include <bits/stdc++.h> using namespace std; const int MAXN = 40005; map<int, int> chl[MAXN]; int fa[MAXN], maxl[MAXN], right_siz[MAXN]; int top = 1, root = 1, last = 1; void push(int x) { int p = last, np = ++top; maxl[np] = maxl[p]+1, right_siz[np] = 1; while (p && !chl[p][x]) chl[p][x] = np, p = fa[p]; if (!p) fa[np] = root; else { int q = chl[p][x]; if (maxl[q] == maxl[p] + 1) fa[np] = q; else { int nq = ++top; maxl[nq] = maxl[p]+1, chl[nq] = chl[q]; fa[nq] = fa[q], fa[q] = fa[np] = nq; while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p]; } } last = np; } struct node { int to, next; } edge[MAXN]; int head[MAXN], tp = 0; void push(int i, int j) { ++tp, edge[tp] = (node){j, head[i]}, head[i] = tp; } int n, k, ans = 0; void dfs(int nd) { for (int i = head[nd]; i; i = edge[i].next) { dfs(edge[i].to); right_siz[nd] += right_siz[edge[i].to]; } if (right_siz[nd] >= k) ans = max(ans, maxl[nd]); } int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { int u; scanf("%d", &u); push(u); } for (int i = 2; i <= top; i++) push(fa[i], i); dfs(root); cout << ans << endl; return 0; }
bzoj3238: [Ahoi2013]差异
约30′。因为longlong WA了一次。
后缀自动机parent树=逆序后缀树,后缀长度=maxl[nd]
#include <bits/stdc++.h> using namespace std; const int MAXN = 500005*2; int chl[MAXN][26], fa[MAXN], maxl[MAXN]; long long right_siz[MAXN]; int top = 1, root = 1, last = 1; void push(int x) { int p = last, np = ++top; maxl[np] = maxl[p]+1, right_siz[np] = 1; while (p && !chl[p][x]) chl[p][x] = np, p = fa[p]; if (!p) fa[np] = root; else { int q = chl[p][x]; if (maxl[q] == maxl[p] + 1) fa[np] = q; else { int nq = ++top; maxl[nq] = maxl[p]+1; memcpy(chl[nq], chl[q], sizeof chl[q]); fa[nq] = fa[q], fa[q] = fa[np] = nq; while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p]; } } last = np; } struct node { int to, next; } edge[MAXN]; int head[MAXN], tp = 0; void push(int i, int j) { edge[++tp] = (node) {j, head[i]}, head[i] = tp; } char str[MAXN]; long long dfs(int nd) { long long ans = 0, beg = right_siz[nd]; for (int i = head[nd]; i; i = edge[i].next) ans += dfs(edge[i].to), right_siz[nd] += right_siz[edge[i].to]; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; ans += right_siz[to]*(right_siz[nd]-right_siz[to])*maxl[nd]; } ans += beg*(right_siz[nd]-beg)*maxl[nd]; return ans; } void init() { scanf("%s", str+1); int n = strlen(str+1); for (int i = n; i >= 1; i--) push(str[i]-'a'); for (int i = 2; i <= top; i++) push(fa[i], i); long long ans = 0; for (int i = 1; i <= n; i++) ans += (long long)(n-i)*(n-i+1ll)+(long long)(1ll+n-i)*(n-i)/2; cout << ans-dfs(root) << endl; } int main() { init(); return 0; }
树相关
树上倍增
NOIP2013 货车运输#include <bits/stdc++.h> using namespace std; const int MAXN = 10005, MAXM = 100005; struct p { int x, y, d; friend bool operator < (const p &a, const p &b) { return a.d > b.d; } } edge_arr[MAXN]; struct node { int to, next, dis; } edge[MAXN]; int head[MAXN], top = 0; void push(int i, int j, int k) { edge[++top] = (node){j, head[i], k}, head[i] = top; } int fa[MAXN]; int findf(int nd) { return fa[nd] ? fa[nd] = findf(fa[nd]) : nd; } int n, m; int depth[MAXN], jmp[MAXN][20], min_val[MAXN][20], vis[MAXN]; void dfs(int nd, int f) { jmp[nd][0] = f, depth[nd] = depth[f] + 1; for (int j = head[nd]; j; j = edge[j].next) { int to = edge[j].to, d = edge[j].dis; if (to == f) continue; min_val[to][0] = d; dfs(to, nd); } } void init() { for (int j = 1; j < 20; j++) for (int i = 1; i <= n; i++) { jmp[i][j] = jmp[jmp[i][j-1]][j-1]; min_val[i][j] = min(min_val[i][j-1], min_val[jmp[i][j-1]][j-1]); } } int lca(int a, int b) { if (depth[a] < depth[b]) swap(a, b); for (int i = 0, d = depth[a]-depth[b]; i < 20; i++) if ((1<<i)&d) a = jmp[a][i]; if (a == b) return a; for (int i = 19; i >= 0; i--) if (jmp[a][i] != jmp[b][i]) a = jmp[a][i], b = jmp[b][i]; return jmp[a][0]; } int query(int a, int b) { int c = lca(a, b); if (findf(a) != findf(b)) return -1; int ans = INT_MAX; for (int i = 0, d = depth[a]-depth[c]; i < 20; i++) if ((1<<i)&d) ans = min(ans, min_val[a][i]), a = jmp[a][i]; for (int i = 0, d = depth[b]-depth[c]; i < 20; i++) if ((1<<i)&d) ans = min(ans, min_val[b][i]), b = jmp[b][i]; return ans; } int main() { memset(min_val, 127/3, sizeof min_val); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) scanf("%d%d%d", &edge_arr[i].x, &edge_arr[i].y, &edge_arr[i].d); sort(edge_arr+1, edge_arr+m+1); for (int i = 1; i <= m; i++) { int u = edge_arr[i].x, v = edge_arr[i].y, d = edge_arr[i].d; if (findf(u) != findf(v)) { fa[findf(u)] = findf(v); push(u, v, d), push(v, u, d); } } depth[0] = 0; for (int i = 1; i <= n; i++) if (fa[i] == 0) dfs(i, 0); init(); int q; scanf("%d", &q); for (int i = 1; i <= q; i++) { int u, v; scanf("%d%d", &u, &v); printf("%d\n", query(u, v)); } return 0; }
树链剖分
luogu模板题约50′
#include <bits/stdc++.h> using namespace std; const int MAXN = 100005; int lc[MAXN], rc[MAXN], l[MAXN], r[MAXN], root = 0; long long sum[MAXN], lazy[MAXN], P; int tp = 0; void build_tree(int &nd, int opl, int opr) { nd = ++tp, l[nd] = opl, r[nd] = opr; sum[nd] = lazy[nd] = 0; if (opl < opr) build_tree(lc[nd], opl, (opl+opr)/2), build_tree(rc[nd], (opl+opr)/2+1, opr); } void pdw(int nd) { if (!lazy[nd]) return; if (lc[nd]) lazy[lc[nd]] += lazy[nd]; if (rc[nd]) lazy[rc[nd]] += lazy[nd]; (sum[nd] += lazy[nd]*(r[nd]-l[nd]+1)) %= P; lazy[nd] = 0; } void modify(int nd, int opl, int opr, long long dt) { if (opl == l[nd] && opr == r[nd]) (lazy[nd] += dt) %= P; else { int mid = (l[nd]+r[nd])/2; (sum[nd] += (opr-opl+1)*dt) %= P; if (opr <= mid) modify(lc[nd], opl, opr, dt); else if (opl >= mid+1) modify(rc[nd], opl, opr, dt); else modify(lc[nd], opl, mid, dt), modify(rc[nd], mid+1, opr, dt); } } long long query(int nd, int opl, int opr) { if (nd) pdw(nd); if (opl == l[nd] && opr == r[nd]) return sum[nd]%P; else { int mid = (l[nd]+r[nd])/2; if (opr <= mid) return query(lc[nd], opl, opr); else if (opl >= mid+1) return query(rc[nd], opl, opr); else return (query(lc[nd], opl, mid)+query(rc[nd], mid+1, opr))%P; } } struct node { int to, next; } edge[MAXN*2]; int head[MAXN], top = 0; void push(int i, int j) { edge[++top] = (node) {j, head[i]}, head[i] = top; } int n, m, rt; int siz[MAXN], id[MAXN], out[MAXN], ind[MAXN], rk[MAXN], depth[MAXN]; int id_in_ds = 0; int fa[MAXN][21]; void dfs(int nd, int f) { fa[nd][0] = f, siz[nd] = 1, depth[nd] = depth[f] + 1; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f) continue; dfs(to, nd), siz[nd] += siz[to]; } } void dfs2(int nd, int from) { id[nd] = ++id_in_ds, ind[nd] = from; modify(root, id[nd], id[nd], rk[nd]); int hev = 0; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (depth[to] < depth[nd]) continue; if (siz[to] > siz[hev]) hev = to; } if (!hev) { out[nd] = id_in_ds; return; } dfs2(hev, from); for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (depth[to] < depth[nd]) continue; if (to != hev) dfs2(to, to); } out[nd] = id_in_ds; } void init() { for (int j = 1; j <= 20; j++) for (int i = 1; i <= n; i++) fa[i][j] = fa[fa[i][j-1]][j-1]; } int lca(int a, int b) { if (depth[a] < depth[b]) swap(a, b); for (int d = depth[a]-depth[b], i = 0; i <= 20; i++) if (d&(1<<i)) a = fa[a][i]; if (a == b) return a; for (int i = 20; i >= 0; i--) if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i]; return fa[a][0]; } void add_path(int a, long long dt) // a到根 { while (a) { modify(root, id[ind[a]], id[a], dt); a = fa[ind[a]][0]; } } void add_son(int a, int dt) { modify(root, id[a], out[a], dt); } long long query_path(int a) // { long long ans = 0; while (a) { (ans += query(root, id[ind[a]], id[a])) %= P; a = fa[ind[a]][0]; } return ans; } long long query_son(int a) { return query(root, id[a], out[a]); } int main() { scanf("%d%d%d%lld", &n, &m, &rt, &P); for (int i = 1; i <= n; i++) scanf("%d", &rk[i]); build_tree(root, 1, n); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); push(u, v), push(v, u); } depth[rt] = 0, dfs(rt, 0); dfs2(rt, rt); init(); for (int i = 1; i <= m; i++) { int tp, x, y; long long z; scanf("%d", &tp); if (tp == 1) { scanf("%d%d%lld", &x, &y, &z); int c = lca(x, y); add_path(x, z), add_path(y, z); add_path(c, -2*z); modify(root, id[c], id[c], z); } else if (tp == 2) { scanf("%d%d", &x, &y); int c = lca(x, y); printf("%lld\n", ((query_path(x)+query_path(y)-2*query_path(c)+query(root, id[c], id[c]))%P+P)%P); } else if (tp == 3) { scanf("%d%lld", &x, &z); add_son(x, z); } else if (tp == 4) { scanf("%d", &x); printf("%lld\n", query_son(x)); } else throw; } return 0; }
dfs序
bzoj4034: [HAOI2015]树上操作这个题其实树剖很好写,不过dfs序的思路太神辣所以必须发…http://www.cnblogs.com/liyinggang/p/5965981.html
pdw写错+10086…
虽然dfs序理论复杂度O(nlgn)但是由于写法太渣跑的还没有链剖快…
#include <bits/stdc++.h> using namespace std; const int MAXN = 100005*8; int n, m; int lc[MAXN], rc[MAXN], l[MAXN], r[MAXN]; long long sum[MAXN], lazy[MAXN]; long long num[MAXN], num_tmp[MAXN]; int root = 0, top_ds = 0; void build(int &nd, int opl, int opr) { nd = ++top_ds, sum[nd] = 0; l[nd] = opl, r[nd] = opr; if (opl < opr) { build(lc[nd], opl, (opl+opr)/2); build(rc[nd], (opl+opr)/2+1, opr); num[nd] = num[lc[nd]] + num[rc[nd]]; } else num[nd] = num_tmp[opl]; } void pdw(int nd) { if (!lazy[nd]) return; sum[nd] += num[nd]*lazy[nd]; if (lc[nd]) lazy[lc[nd]] += lazy[nd]; if (rc[nd]) lazy[rc[nd]] += lazy[nd]; lazy[nd] = 0; } void modify(int nd, int opl, int opr, long long dat) { if (opl == l[nd] && opr == r[nd]) lazy[nd] += dat, pdw(nd); else { pdw(nd); int mid = (l[nd]+r[nd])>>1; if (opr <= mid) modify(lc[nd], opl, opr, dat); else if (opl >= mid+1) modify(rc[nd], opl, opr, dat); else modify(lc[nd], opl, mid, dat), modify(rc[nd], mid+1, opr, dat); pdw(lc[nd]), pdw(rc[nd]); sum[nd] = sum[lc[nd]] + sum[rc[nd]]; } } void display(int nd, int tab) { if (!nd) return; for (int i = 1; i <= tab; i++) putchar(' '); printf("[%d,%d] --> sum = %lld, lazy = %lld, num = %lld\n", l[nd], r[nd], sum[nd], lazy[nd], num[nd]); display(lc[nd], tab+2); display(rc[nd], tab+2); } long long query(int nd, int opl, int opr) { pdw(nd); if (opl == l[nd] && opr == r[nd]) return sum[nd]; else { int mid = (l[nd]+r[nd])>>1; if (opr <= mid) return query(lc[nd], opl, opr); else if (opl >= mid+1) return query(rc[nd], opl, opr); else return query(lc[nd], opl, mid)+query(rc[nd], mid+1, opr); } } struct node { int to, next; } edge[MAXN]; int head[MAXN], top = 0; void push(int i, int j) { edge[++top] = (node) {j, head[i]}, head[i] = top; } int in[MAXN], out[MAXN], ds_top = 0; int rk[MAXN]; void dfs(int nd, int f) { in[nd] = ++ds_top; num_tmp[in[nd]] = 1; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f) continue; dfs(to, nd); } out[nd] = ++ds_top; num_tmp[out[nd]] = -1; } void modify_point(int nd, long long dt) { modify(root, in[nd], in[nd], dt); modify(root, out[nd], out[nd], dt); } void modify_tree(int nd, long long dt) { modify(root, in[nd], out[nd], dt); } long long query_path(int nd) { return query(root, in[1], in[nd]); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &rk[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); push(u, v), push(v, u); } dfs(1, 0); build(root, 1, 2*n); for (int i = 1; i <= n; i++) { modify_point(i, rk[i]); } for (int i = 1; i <= m; i++) { int tp, a; long long b; scanf("%d", &tp); if (tp == 1) { scanf("%d%lld", &a, &b); modify_point(a, b); } else if (tp == 2) { scanf("%d%lld", &a, &b); modify_tree(a, b); } else { scanf("%d", &a); printf("%lld\n", query_path(a)); } } return 0; }
lct
bzoj3832 Treehttp://hzwer.com/4422.html
约1.5h,脑残原因:zig的时候先修改了p的fa,才判断is_rt(p)…
#include <bits/stdc++.h> using namespace std; const int MAXN = 500005; int chl[MAXN][2], fa[MAXN], dat[MAXN], sum[MAXN], top = 0; int rev[MAXN], stk[MAXN], stop = 0, n, m; bool is_rt(int nd) { return chl[fa[nd]][0] != nd && chl[fa[nd]][1] != nd; } void pdw(int nd) { if (!rev[nd]) return; int &lc = chl[nd][0], &rc = chl[nd][1]; if (lc) rev[lc] ^= 1; if (rc) rev[rc] ^= 1; swap(lc, rc), rev[nd] = 0; } inline void update(int nd) { sum[nd] = dat[nd]^sum[chl[nd][0]]^sum[chl[nd][1]]; } void zig(int nd) { int p = fa[nd], g = fa[p]; int tp = chl[p][0] != nd, tg = chl[g][0] != p; int son = chl[nd][tp^1]; if (!is_rt(p)) chl[g][tg] = nd; fa[son] = p, fa[p] = nd, fa[nd] = g; chl[nd][tp^1] = p, chl[p][tp] = son; update(p), update(nd); } void splay(int nd) { stk[stop = 1] = nd; for (int i = nd; !is_rt(i); i = fa[i]) stk[++stop] = fa[i]; while (stop) pdw(stk[stop--]); while (!is_rt(nd)) { int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p; if (is_rt(p)) { zig(nd); break; } else if (tp == tg) zig(p), zig(nd); else zig(nd), zig(nd); } } void access(int x) { for (int y = 0; x; x = fa[y = x]) splay(x), chl[x][1] = y, update(x); } void make_rt(int x) { access(x), splay(x); rev[x] ^= 1; } int find_fa(int x) { access(x), splay(x); while (chl[x][0]) { if (x == chl[x][0]) throw; x = chl[x][0]; } return x; } void link(int x, int y) { if (find_fa(x) == find_fa(y)) return; make_rt(x), fa[x] = y; access(x); } void cut(int x, int y) { if (find_fa(x) != find_fa(y)) return; make_rt(x); access(y), splay(y); if (chl[y][0] == x) chl[y][0] = 0, fa[x] = 0; } int query(int x, int y) { make_rt(x), access(y), splay(y); if (find_fa(y) != x) return -1; return sum[y]; } void change(int x, int dt) { make_rt(x), splay(x), dat[x] = dt, update(x); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &dat[i]), update(i); for (int i = 1; i <= m; i++) { int tp, x, y; scanf("%d%d%d", &tp, &x, &y); if (tp == 0) printf("%d\n", query(x, y)); else if (tp == 1) link(x, y); else if (tp == 2) cut(x, y); else change(x, y); } return 0; }
bzoj2843: 极地旅行社
Description
不久之前,Mirko建立了一个旅行社,名叫“极地之梦”。这家旅行社在北极附近购买了N座冰岛,并且提供观光服务。当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间。Mirko的旅行社遭受一次
重大打击,以至于观光游轮已经不划算了。旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客。Mirko希望
开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生。这些冰岛从1到N标号。一开始时这些
岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的。每座岛上的企鹅数量虽然会有所改变,但是始终在[0
, 1000]之间。你的程序需要处理以下三种命令:
1.”bridge A B”——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当
A与B不联通。若这项命令被接受,你的程序需要输出”yes”,之
后会建造这座大桥。否则,你的程序需要输出”no”。
2.”penguins A X”——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不
需要回应。
3.”excursion A B”——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的
帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出”impossible”。
Input
第一行一个正整数N,表示冰岛的数量。第二行N个范围[0,1000]的整数,为每座岛屿初始的帝企鹅数量。
第三行一个正整数M,表示命令的数量。接下来M行即命令,为题目描述所示。
1<=N<=30000,1<=M<=100000
16′04′′
#include <bits/stdc++.h> using namespace std; const int MAXN = 30005; int chl[MAXN][2], fa[MAXN], rev[MAXN], stk[MAXN], sum[MAXN], dat[MAXN], top = 0; inline bool is_rt(int nd) { return chl[fa[nd]][0] != nd && chl[fa[nd]][1] != nd; } inline void update(int nd) { sum[nd] = sum[chl[nd][0]]+sum[chl[nd][1]]+dat[nd]; } void pdw(int nd) { if (!rev[nd]) return; int &lc = chl[nd][0], &rc = chl[nd][1]; if (lc) rev[lc] ^= 1; if (rc) rev[rc] ^= 1; swap(lc, rc), rev[nd] = 0; } void zig(int nd) { int p = fa[nd], g = fa[p]; int tp = chl[p][0] != nd, tg = chl[g][0] != p, son = chl[nd][tp^1]; if (son) fa[son] = p; if (!is_rt(p)) chl[g][tg] = nd; fa[p] = nd, fa[nd] = g; chl[nd][tp^1] = p, chl[p][tp] = son; update(p), update(nd); } void splay(int nd) { stk[top = 1] = nd; for (int i = nd; !is_rt(i); i = fa[i]) stk[++top] = fa[i]; while (top) pdw(stk[top--]); while (!is_rt(nd)) { int p = fa[nd], g = fa[p]; int tp = chl[p][0] != nd, tg = chl[g][0] != p; if (is_rt(p)) {zig(nd); break; } else if (tp == tg) zig(p), zig(nd); else zig(nd), zig(nd); } } void access(int x) { for (int y = 0; x; x = fa[y = x]) splay(x), chl[x][1] = y, update(x); } void make_rt(int x) { access(x), splay(x), rev[x] ^= 1; } int find(int x) { access(x), splay(x); while (chl[x][0]) x = chl[x][0]; return x; } void link(int x, int y) { if (find(x) == find(y)) return; make_rt(x), access(x), splay(x); fa[x] = y; } void change(int x, int dt) { make_rt(x), splay(x), dat[x] = dt, update(x); } int query(int x, int y) { return make_rt(x), access(y), splay(y), sum[y]; } int n, m; char str[20]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d",&dat[i]), update(i); scanf("%d", &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%s %d %d", str, &x, &y); if (str[0] == 'e') { if (find(x) != find(y)) puts("impossible"); else printf("%d\n", query(x, y)); } else if (str[0] == 'p') { change(x, y); } else if (str[0] == 'b') { if (find(x) == find(y)) puts("no"); else puts("yes"), link(x, y); } } return 0; }
数据结构
splay
bzoj1269: [AHOI2006]文本编辑器editor被pdw支配的恐惧…
几个小操作的先后顺序一定要小心小心再小心啊…这次由于先检查siz后pushdown导致1h+调试…
约2h
#include <bits/stdc++.h> using namespace std; const int MAXN = 1024*1024*4; int chl[MAXN][2], fa[MAXN], dat[MAXN], siz[MAXN], rev[MAXN]; int top = 0, root = 0; inline void update(int nd) { if(!nd) return; siz[nd] = siz[chl[nd][0]]+siz[chl[nd][1]]+1; } int stk[MAXN], skp = 0; void pdw(int nd) { if (!rev[nd]) return; int &lc = chl[nd][0], &rc = chl[nd][1]; rev[lc] ^= (lc != 0), rev[rc] ^= (rc != 0); swap(lc, rc), rev[nd] = 0; } void zig(int nd) { pdw(nd); int p = fa[nd], g = fa[p]; int tp = chl[p][0] != nd, tg = chl[g][0] != p, son = chl[nd][tp^1]; if (g) chl[g][tg] = nd; else root = nd; if (son) fa[son] = p; chl[nd][tp^1] = p, chl[p][tp] = son; fa[p] = nd, fa[nd] = g; update(p), update(nd); } void splay(int nd, int tar = 0) { stk[skp = 1] = nd; for (int i = nd; fa[i]; i = fa[i]) stk[++skp] = fa[i]; while (skp) pdw(stk[skp--]); while (fa[nd] != tar) { int p = fa[nd], g = fa[p]; int tp = chl[p][0] != nd, tg = chl[g][0] != p; if (g == tar) {zig(nd); break; } else if (tp == tg) zig(p), zig(nd); else zig(nd), zig(nd); } } void dfs(int nd, int key) { if (!nd) return; // pdw(nd); // for (int i = 1; i <= tab; i++) putchar(' '); printf("nd = %d, lc = %d, rc = %d, dat = %c, fa = %d-- siz = %d, rev = %d\n", nd, chl[nd][0], chl[nd][1], dat[nd], fa[nd], siz[nd], rev[nd]); dfs(chl[nd][0], key); // putchar(dat[nd]); if (key == nd) putchar('|'); dfs(chl[nd][1], key); } int kth(int k) { int nd = root; while (pdw(nd), siz[chl[nd][0]] != k) { nd = siz[chl[nd][0]] > k ? chl[nd][0] : (k -= siz[chl[nd][0]]+1, chl[nd][1]); } return nd; } int rk(int nd) { splay(nd); return siz[chl[nd][0]]; } int go_prev(int nd) { return kth(rk(nd)-1); } int go_next(int nd) { return kth(rk(nd)+1); } void print(int nd) { putchar(dat[go_next(nd)]); puts(""); } int insert(int nd, int x) { int nx = go_next(nd); splay(nd); splay(nx, root); pdw(root), pdw(nx); chl[nx][0] = ++top, fa[top] = nx, dat[top] = x, update(top), update(nx), update(nd); return top; } void del(int nd, int len) { int l = nd, r = kth(rk(nd)+len+1); splay(l), splay(r, root); pdw(l), pdw(r); chl[r][0] = 0, update(r), update(l); } int reverse(int nd, int len) { int l = nd, r = kth(rk(nd)+len+1), k = rk(nd); splay(l), splay(r, root); pdw(l), pdw(r); rev[chl[r][0]] ^= 1; return kth(k); } int n, k; char str[20], s[MAXN]; void get_str(char str[]) { int k = -1, c; do c = getchar(); while(c < 32 || c > 126); while (c >= 32 && c <= 126) { str[++k] = c; c = getchar(); } str[++k] = '\0'; } int main() { root = ++top, dat[top] = 0, chl[root][1] = ++top, dat[top] = 1; fa[top] = top-1; update(top), update(top-1); scanf("%d", &n); int nd = top-1; for (int i = 1; i <= n; i++) { scanf("%s", str); switch(str[0]) { case 'M': scanf("%d", &k); nd = kth(k); break; case 'I': scanf("%d", &k); get_str(s); for (int i = 0, x = nd; i < k; i++) x = insert(x, s[i]); break; case 'D': scanf("%d", &k), del(nd, k); break; case 'R': scanf("%d", &k), nd = reverse(nd, k); break; case 'G': print(nd); break; case 'P': nd = go_prev(nd); break; case 'N': nd = go_next(nd); break; } } return 0; }
线段树
主席树
无修改区间k大。#include <bits/stdc++.h> using namespace std; const int MAXN = 100005, lgn = 21; int lc[MAXN*lgn], rc[MAXN*lgn], l[MAXN*lgn], r[MAXN*lgn], sum[MAXN*lgn]; int root[MAXN], top = 0; int n, m; void build(int &nd, int opl, int opr) { nd = ++top; l[nd] = opl, r[nd] = opr, sum[nd] = 0; if (opl < opr) build(lc[nd], opl, (opl+opr)/2), build(rc[nd], (opl+opr)/2+1, opr); } void push(int prev, int &nd, int pos) { nd = ++top; l[nd] = l[prev], r[nd] = r[prev]; if (l[prev] == r[prev]) sum[nd] = sum[prev]+1; else { int mid = (l[prev]+r[prev])/2; if (pos <= mid) push(lc[prev], lc[nd], pos), rc[nd] = rc[prev]; else push(rc[prev], rc[nd], pos), lc[nd] = lc[prev]; sum[nd] = sum[lc[nd]]+sum[rc[nd]]; } } void dfs(int nd, int tab = 0) { if (!nd) return; for (int i = 1; i <= tab; i++) putchar(' '); printf("[%d,%d] -- sum = %d\n", l[nd], r[nd], sum[nd]); dfs(lc[nd], tab+2), dfs(rc[nd], tab+2); } int query(int opl, int opr, int k) { int i = 1, j = n, mid; int a = root[opl-1], b = root[opr]; k--; while (i < j) { mid = (i+j)>>1; if (sum[lc[b]]-sum[lc[a]] <= k) k -= sum[lc[b]]-sum[lc[a]], i = mid+1, a = rc[a], b = rc[b]; else j = mid, a = lc[a], b = lc[b]; } return i; } int d[MAXN]; int dx[MAXN]; void dx_init() { memcpy(dx, d, sizeof d); sort(dx+1, dx+n+1); } int dx_num(int nd) { return lower_bound(dx+1, dx+n+1, nd)-dx; } int main() { scanf("%d%d", &n, &m); build(root[0], 1, n); for (int i = 1; i <= n; i++) scanf("%d", &d[i]); dx_init(); for (int i = 1; i <= n; i++) { push(root[i-1], root[i], dx_num(d[i])); } for (int i = 1; i <= m; i++) { int u, v, k; scanf("%d%d%d", &u, &v, &k); cout << dx[query(u, v, k)] << endl; } return 0; }
其他
FFT
大爷题解:http://www.cnblogs.com/iiyiyi/p/5717520.html好像把一道好题变成练模板了..之后补分析吧..
#include <bits/stdc++.h> using namespace std; const int MAXN = 300005; int rev[MAXN], n; typedef complex<double> Complex; Complex A[MAXN]; const double PI = acos(-1); void fft(Complex a[], int n, int flag) { int lgn = int(log2(n)+0.01); rev[0] = 0; for (int i = 1; i < n; i++) rev[i] = (rev[i>>1]>>1)|((1<<(lgn-1))*(i&1)); for (int i = 0; i < n; i++) A[i] = a[rev[i]]; for (int k = 2; k <= n; k <<= 1) { Complex dw = Complex(cos(2*PI/k), flag*sin(2*PI/k)); for (int i = 0; i < n; i += k) { Complex w = Complex(1, 0), u, v; for (int j = 0; j < (k>>1); j++) { u = A[i+j], v = w*A[i+j+(k>>1)]; A[i+j] = u+v, A[i+j+(k>>1)] = u-v; w *= dw; } } } for (int i = 0; i < n; i++) a[i] = A[i]/(flag==1?Complex(1,0):Complex(n,0)); } long long k[MAXN]; int dat[MAXN]; Complex a[MAXN], b[MAXN], c[MAXN]; int main() { scanf("%d", &n); int N = 1, mx = 0; for (int i = 0; i < n; i++) { int t; scanf("%d", &t); dat[i] = t; mx = max(mx, t); a[t] += Complex(1, 0); b[2*t] += Complex(1, 0); c[3*t] += Complex(1, 0); } while (N <= mx*3) N<<=1; fft(a, N, 1), fft(b, N, 1), fft(c, N, 1); for (int i = 0; i < N; i++) a[i]=(a[i]*a[i]*a[i]-Complex(3, 0)*a[i]*b[i]+Complex(2, 0)*c[i])/Complex(6, 0)+(a[i]*a[i]-b[i])/Complex(2, 0)+a[i]; fft(a, N, -1); for (int i = 0; i < N; i++) { k[i] += (long long)(a[i].real()+0.1); } for (int i = 0; i < N; i++) if (k[i]) printf("%d %lld\n", i, k[i]); return 0; }
Tarjan
bzoj2140 稳定婚姻#include <bits/stdc++.h> using namespace std; const int MAXN = 10005, MAXM = 100005; struct node { int to, next; } edge[MAXM]; int head[MAXN], top = 0; void push(int i, int j) { edge[++top] = (node){j, head[i]}, head[i] = top; } int dfn[MAXN], low[MAXN], stk[MAXN], instk[MAXN], stop = 0, dfs_top = 0; int gp[MAXN], gp_top = 0; int n, m, strtop = 0; map<string, int> tab; string str[MAXN]; string s1, s2; void tarjan(int nd) { stk[++stop] = nd, instk[nd] = 1, dfn[nd] = low[nd] = ++dfs_top; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (!dfn[to]) tarjan(to), low[nd] = min(low[nd], low[to]); else if (instk[to]) low[nd] = min(low[nd], dfn[to]); } if (dfn[nd] == low[nd]) { int now = 0; gp_top++; // printf(" -- Group %d --\n", gp_top); do { now = stk[stop--]; gp[now] = gp_top; instk[now] = 0; // cerr << str[now] << " "; } while (now != nd); // puts(""); } } int cpx[MAXN], cpy[MAXN]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { cin >> s1 >> s2; if (!tab.count(s1)) tab[s1] = ++strtop, str[strtop] = s1; if (!tab.count(s2)) tab[s2] = ++strtop, str[strtop] = s2; push(tab[s2], tab[s1]); cpx[i] = tab[s1], cpy[i] = tab[s2]; } scanf("%d", &m); for (int i = 1; i <= m; i++) { cin >> s1 >> s2; push(tab[s1], tab[s2]); } for (int i = 1; i <= strtop; i++) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; i++) if (gp[cpx[i]] == gp[cpy[i]]) puts("Unsafe"); else puts("Safe"); return 0; }
dinic
CQOI2015 网络吞吐量spfa居然写跪了…没救了这
#include <bits/stdc++.h> using namespace std; const int MAXN = 2005, MAXM = 200005; struct node { int to, next; long long flow; int neg; } edge[MAXM]; int head[MAXN], top = 0; void push(int i, int j, long long f) { ++top, edge[top] = (node){j, head[i], f, top+1}, head[i] = top; ++top, edge[top] = (node){i, head[j], 0, top-1}, head[j] = top; } const long long inf = 23333333333333ll; int S, T, n, m; int lev[MAXN], vis[MAXN], bfstime = 0; queue<int> que; bool bfs() { que.push(S), lev[S] = 0, vis[S] = ++bfstime; while (!que.empty()) { int t = que.front(); que.pop(); for (int i = head[t]; i; i = edge[i].next) { int to = edge[i].to; long long d = edge[i].flow; if (!d || vis[to] == bfstime) continue; vis[to] = bfstime, que.push(to), lev[to] = lev[t]+1; } } return vis[T] == bfstime; } long long dfs(int nd, long long flow = inf) { if (!flow || nd == T) return flow; long long t, ans = 0; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; long long d = edge[i].flow; if (!d || lev[to] != lev[nd]+1) continue; t = dfs(to, min(flow, d)); ans += t, flow -= t; edge[i].flow -= t, edge[edge[i].neg].flow += t; } if (flow) lev[nd] = -1; return ans; } long long dinic() { long long ans = 0; while (bfs()) ans += dfs(S); return ans; } long long dis[MAXN]; int inq[MAXN]; long long rk[MAXN]; node g2[MAXM]; int h2[MAXN], tp = 0; void push2(int i, int j, long long k) { ++tp, g2[tp] = (node){j, h2[i], k, 0}, h2[i] = tp; } void spfa() { memset(dis, 127/3, sizeof dis); memset(inq, 0, sizeof inq); dis[S] = 0, que.push(S), inq[S] = 1; while (!que.empty()) { int t = que.front(); que.pop(), inq[t] = 0; for (int i = h2[t]; i; i = g2[i].next) { int to = g2[i].to, d = g2[i].flow; if (dis[to] > dis[t] + d) { dis[to] = dis[t] + d; if (!inq[to]) inq[to] = 1, que.push(to); } } } } int main() { scanf("%d%d", &n, &m), S = 1, T = n+n; for (int i = 1; i <= m; i++) { int u, v; long long d; scanf("%d%d%lld", &u, &v, &d); push2(u, v, d), push2(v, u, d); } for (int i = 1; i <= n; i++) scanf("%lld", &rk[i]); spfa(); for (int i = 1; i <= n; i++) for (int j = h2[i]; j; j = g2[j].next) { int to = g2[j].to; long long d = g2[j].flow; if (dis[to] == dis[i] + d) { push(i+n, to, inf); // cout << i << "--" << d << "->" << to << endl; } } push(1, n+1, inf), push(n, n+n, inf); for (int i = 2; i < n; i++) push(i, i+n, rk[i]); cout << dinic() << endl; return 0; }
spfa费用流
[Noi2008]志愿者招募#include <bits/stdc++.h> using namespace std; const int MAXN = 2005, MAXM = 100005; struct node { int to, next; long long flow, cost; int neg; } edge[MAXM]; int head[MAXN], top = 0, S = 2000, T = 2001; long long inf = 23333333333333ll; void push(int i, int j, long long f, long long c) { ++top, edge[top] = (node){j, head[i], f, c, top+1}, head[i] = top; ++top, edge[top] = (node){i, head[j], 0, -c, top-1}, head[j] = top; } void push_lim(int i, int j, long long mf) { push(S, j, mf, 0), push(i, T, mf, 0); push(i, j, inf, 0); } long long dis[MAXN]; int vis[MAXN], pre[MAXN], pre_edge[MAXN], n, m; queue<int> que; bool spfa(long long &cost) { memset(dis, 127/3, sizeof dis); memset(vis, 0, sizeof vis); memset(pre, 0, sizeof pre); memset(pre_edge, 0, sizeof pre_edge); vis[S] = 1, dis[S] = 0, que.push(S); while (!que.empty()) { int t = que.front(); que.pop(); vis[t] = 0; for (int i = head[t]; i; i = edge[i].next) { int to = edge[i].to, c = edge[i].cost; if (!edge[i].flow) continue; if (dis[to] > dis[t] + c) { dis[to] = dis[t] + c; pre[to] = t, pre_edge[to] = i; if (!vis[to]) vis[to] = 1, que.push(to); } } } if (dis[T] >= inf) return 0; long long mf = inf; for (int i = T; i != S; i = pre[i]) mf = min(mf, edge[pre_edge[i]].flow); for (int i = T; i != S; i = pre[i]) edge[pre_edge[i]].flow -= mf, edge[edge[pre_edge[i]].neg].flow += mf; cost += dis[T]*mf; return 1; } long long mcf() { long long ans = 0; while (spfa(ans)); return ans; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { long long u; scanf("%lld", &u); push_lim(i, i+1, u); } for (int i = 1; i <= m; i++) { int l, r; long long cost; scanf("%d%d%lld", &l, &r, &cost); push(r+1, l, inf, cost); } cout << mcf() << endl; return 0; }
相关文章推荐
- 【反演复习计划】【COGS2432】爱蜜莉雅的施法
- 西北工业大学2008算法机试 复习计划
- 考研复习计划(8.20-8.31)
- [NOIp复习计划]:图的连通
- Cpp复习(三)template library and c++11
- [复习计划]IMS5024
- C++复习——template,template类,memcmp
- [置顶] NOIP 2017 复习计划
- 西北工业大学2008算法机试 复习计划
- 突出重点马原!2018考研政治暑期复习完整计划
- 6个月新GRE复习计划分享
- 系分复习计划1
- 复习计划(第一次筛选)
- 快来抄吧:Project Plan Template 项目计划模板
- [梦梦]_考研,复习计划
- 近期复习计划
- 【反演复习计划】【bzoj2818】gcd
- 【反演复习计划】【COGS2431】爱蜜莉雅的求助
- 考托福复习计划
- 复习计划