[wc2013]糖果公园(70分)-by小雨
本文是一篇关于的帖子
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #define REP(i, n) for (i = 0; i < (n); ++i) #define FER(i, j) for (i = lst[j]; i; i = i->n) #define int64 long long #ifdef WIN32 #define fmt64 "%I64d" #else #define fmt64 "%lld" #endif #define oo 0x13131313 #define maxn 90002 #define BLOCK 300 using namespace std; double now; template<class T> void read(T &x) { char c = getchar(); for (; '0' > c || c > '9'; c = getchar()); x = c - '0', c = getchar(); for (; '0' <= c && c <= '9'; c = getchar()) x = x * 10 + c - '0'; } int n, m, Q, w[maxn], c[maxn]; short Mod[maxn]; int64 v[maxn]; int pa[maxn], size[maxn], ufs[maxn], dep[maxn], dfn[maxn], Dfn, ca[maxn]; int F, f, mark[maxn], tot, a[maxn], Mark; int64 buf[maxn * BLOCK], *buft = buf, *ans[maxn], *Ans; struct edge { int t; edge *n; } edges[maxn * 2], *adj = edges, *lst[maxn], *fr[maxn]; struct block { int a[BLOCK]; } blocks[maxn + BLOCK], *btot = blocks; struct array { block *a[BLOCK]; int operator[](int); } sum[maxn]; int array::operator[](int b) { return --b, a[b / BLOCK]->a[Mod[b]]; } void inherit(array &a, array &b, int pos) { block *&p = a.a[--pos / BLOCK]; memcpy(&a, &b, sizeof(array)), memcpy(btot, p, sizeof(block)); p = btot++, ++p->a[Mod[pos]]; } int find(int x) { int f, g; for (f = x; ufs[f] != f; f = ufs[f]); for (; ufs[x] != x; x = g) g = ufs[x], ufs[x] = f; return f; } void dfs(int u, int fa) { edge *e; int f = -1; inherit(sum[u], sum[fa], c[u]), dep[u] = dep[fa] + 1, dfn[u] = ++Dfn; FER(e, u) if (e->t != fa) { dfs(e->t, u), fr[e->t] = e, pa[e->t] = u; if (!~f || size[f] + size[e->t] > BLOCK << 1) f = e->t; else size[f] += size[e->t], ca[f] = u, ufs[e->t] = f; } ca[u] = ufs[u] = u, size[u] = 1; if (~f && size[f] < BLOCK) size[u] += size[f], ufs[f] = u; } void bfs(int S) { static int q[maxn]; int h, t; edge *e; for (q[h = t = S] = 0; h; h = q[h]) { Ans[h] = Ans[pa[h]] + v[c[h]] * w[sum[F][c[h]] - (sum[f][c[h]] << 1) + sum[h][c[h]] + (c[f] == c[h])]; FER(e, h) if (e->t != pa[h]) q[t = q[t] = e->t] = 0; } } void init()/*pretreat for the answers between blocks*/ { int i, j; edge *e; REP(i, BLOCK) sum->a[i] = btot++; dfs(1, 0); fprintf(stderr, "%.2lf\n", (clock() - now) / CLOCKS_PER_SEC); REP(i, n) if (find(i + 1) == i + 1) { F = f = ca[i + 1]; if (ans[f]) continue; buft += n, Ans = ans[f] = buft - n - 1; Ans[f] = v[c[f]] * w[1]; FER(e, f) if (e->t != pa[f]) bfs(e->t); for (j = f; fr[j]; j = f) { f = pa[j]; Ans[f] = Ans[j] + v[c[f]] * w[sum[F][c[f]] - sum[f][c[f]] + 1]; for (e = fr[j]->n; e; e = e->n) if (e->t != pa[f]) bfs(e->t); } } } int64 ask(int x, int y) { int i, j, f; int64 res = 0; ++Mark, tot = 0; for (i = x; i; i = pa[i]) mark[i] = Mark; for (f = y; mark[f] < Mark; f = pa[f]) a[++tot] = c[f]; a[++tot] = c[f]; for (i = x; i != f; i = pa[i]) a[++tot] = c[i]; sort(a + 1, a + tot + 1); for (i = 1; i <= tot; ) for (j = 0, f = a[i]; a[i] == f && i <= tot; ++i) res += v[f] * w[++j]; return res; } void Dfs(int u, int fa) { edge *e; pa[u] = fa; for (e = lst[u]; e; e = e->n) if (e->t != fa) Dfs(e->t, u); } void input() { int i; scanf("%d%d%d", &n, &m, &Q); REP(i, m) read(v[i + 1]); REP(i, n) read(w[i + 1]), Mod[i] = i % BLOCK; REP(i, n - 1) { int a, b; read(a), read(b); *adj = (edge){b, lst[a]}, lst[a] = adj++; *adj = (edge){a, lst[b]}, lst[b] = adj++; } REP(i, n) read(c[i + 1]); if (n <= 20000 && m <= 20000) { for (Dfs(1, 0); Q--; ) { int t, x, y; read(t), read(x), read(y); t ? printf(fmt64"\n", ask(x, y)) : c[x] = y; } exit(0); } } int LCA(int x, int y) { for (; x != y; ) ufs[x] == ufs[y] ? dep[x] > dep[y] ? x = pa[x] : y = pa[y] : dep[ufs[x]] > dep[ufs[y]] ? x = pa[ufs[x]] : y = pa[ufs[y]]; return x; } int main() { freopen("park.in", "r", stdin); freopen("park.out", "w", stdout); now = clock(); input(); init(); fprintf(stderr, "%.2lf\n", (clock() - now) / CLOCKS_PER_SEC); for (; Q--; ) { int t, x, y; read(t), read(x), read(y); if (!t) exit(0); if (dfn[y] < dfn[x]) swap(x, y); int f = ca[ufs[x]], g = LCA(x, y); int64 Ans = ans[f][y]; if (dep[f] < dep[g]) { for (t = pa[g]; t != pa[f]; t = pa[t]) Ans -= v[c[t]] * w[sum[y][c[t]] - sum[t][c[t]] + 1]; f = g; } for (t = x; t != f; t = pa[t]) Ans += v[c[t]] * w[sum[y][c[t]] - (sum[g][c[t]] << 1) + sum[t][c[t]] + (c[g] == c[t])]; printf(fmt64"\n", Ans); } fprintf(stderr, "%.2lf\n", (clock() - now) / CLOCKS_PER_SEC); }
文章结束给大家分享下程序员的一些笑话语录: 这年头的互联网真是娱乐了中国,网民们从各种各样的“门”里钻来钻去,又有好多“哥”好多“帝”,值得大家品味不已……网络经典语录,关于IT与互联网,经典与您分享!