@ljt12138
2017-04-22T01:33:54.000000Z
字数 26558
阅读 1035
#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;}
#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]; // 两次collectint 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;}
第二次
#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;}
luogu2852
#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]差异
约
后缀自动机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模板题
约
#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;}
bzoj4034: [HAOI2015]树上操作
这个题其实树剖很好写,不过dfs序的思路太神辣所以必须发...http://www.cnblogs.com/liyinggang/p/5965981.html
pdw写错+10086...
虽然dfs序理论复杂度
#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;}
bzoj3832 Tree
http://hzwer.com/4422.html
约
#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: 极地旅行社
不久之前,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"。
第一行一个正整数N,表示冰岛的数量。
第二行N个范围[0,1000]的整数,为每座岛屿初始的帝企鹅数量。
第三行一个正整数M,表示命令的数量。接下来M行即命令,为题目描述所示。
1<=N<=30000,1<=M<=100000
#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");elseputs("yes"), link(x, y);}}return 0;}
bzoj1269: [AHOI2006]文本编辑器editor
被pdw支配的恐惧...
几个小操作的先后顺序一定要小心小心再小心啊...这次由于先检查siz后pushdown导致
约
#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;}
大爷题解: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;}
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");elseputs("Safe");return 0;}
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;}
[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;}