· 蒟蒻题解, 大神轻虐
· 各种丑代码
· 各种绕弯子
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
Delayyy君吐槽这题本机测比OJ快一倍……
于是就去写了写.
树链剖分 or LCT , 各种乱搞.
本机:树链剖分4s+, LCT 8s+ (太懒了直接代入结构体……各种萎)
OJ :树链剖分4s+, LCT 10s+
……我是没什么意见啦
但Delayyy君也是10s+ 本机却只有6s
OJ 的 O2- 抽风了, 诶?
非常非常……裸的代码题.
树链剖分或者LCT都能水过. 诶不知道 ? 度娘文库里有的是……我就不摆出来了 (还是因为懒...)
不过今天写的时候发现了一些问题……
1、子树信息pushdown. 这个原来一直写revroot, 也就是先找到根然后pushdown下来再旋上去. 不过今天突然想到压根就没那必要吧……
只需要在rotate操作里先 pushdown (f[x]), 然后 pushdown(x) 就可以了.
2、关于树的遍历. 本机上Delayyy君被某条链爆栈了……改BFS即可过. LCT因为初始化只需要保存父节点, 所以以后还是用BFS算了……
以防出题人节操丧失.
3、update 的 update_size 为啥一定要写啊我> <~ 有的时候不是根本没必要的么......
代码以下, 版本 1 树链剖分, 版本 2 LCT.
#include <cstdio>
#include <cstdlib>
#include <algorithm>
char ch;
#define max(A, B)
#define son (k << 1)
#define mid ((l + r) >> 1)
#define gs (ch < '0' || ch > '9')
int getint() { int wis = 0; ch = getchar(); while (gs) ch = getchar(); while (!gs) wis = wis * 10 + ch - '0', ch = getchar(); return wis; }
const int ys = 300010;
using namespace std;
bool t[ys];
int n, m, nowp, sg, x, y, co;
int size[ys], da[ys], f[ys], up[ys], point[ys], v[ys], d[ys];
int g[ys], next[ys * 2], c[ys * 2], col[ys], push[ys * 4];
struct Lek
{
int left, right, tot;
} p[ys * 4];
void dfs(int z)
{
t[z] = true; size[z] = 1; int w = 0;
for (int x = g[z]; x; x = next[x])
if (!t[c[x]])
if (dfs(c[x]), size[z] += size[c[x]], size[c[x]] > w)
point[z] = x, w = size[c[x]];
}
void mak(int z, int dt)
{
t[z] = false; v[++sg] = z; da[z] = sg; f[z] = nowp; d[z] = dt;
if (point[z]) mak(c[point[z]], dt);
for (int x = g[z]; x; x = next[x])
if (t[c[x]]) up[c[x]] = z, nowp = c[x], mak(c[x], dt + 1);
}
void marge(Lek &a, Lek b)
{
a.tot += b.tot;
if (a.left == b.right) a.tot--;
if (!a.right) a.right = b.right;
if (b.left) a.left = b.left;
}
Lek build(int l, int r, int k)
{
if (l == r) return p[k] = (Lek){col[v[l]], col[v[l]], 1};
p[k] = build(mid + 1, r, son + 1);
return marge(p[k], build(l, mid, son)), p[k];
}
void pus(int k)
{
if (push[k])
p[son].right = p[son].left = p[son + 1].right = p[son + 1].left = push[k],
p[son].tot = p[son + 1].tot = 1, push[son + 1] = push[son] = push[k], push[k] = 0;
}
Lek tot(int x, int y, int l, int r, int k)
{
pus(k);
if (y < l || x > r) return (Lek){0, 0, 0};
if (x <= l && y >= r) return p[k];
Lek q = tot(x, y, mid + 1, r, son + 1);
return marge(q, tot(x, y, l, mid, son)), q;
}
void cov(int x, int y, int c, int l, int r, int k)
{
if (y < l || x > r) return; pus(k);
if (x <= l && y >= r) p[k] = (Lek){c, c, 1}, push[k] = c;
else cov(x, y, c, l, mid, son), cov(x, y, c, mid + 1, r, son + 1),
p[k] = p[son + 1], marge(p[k], p[son]);
}
int query(int x, int y)
{
Lek y_tot = {0, 0, 0}, x_tot = {0, 0, 0};
while (f[x] != f[y])
if (d[f[x]] < d[f[y]]) marge(y_tot, tot(da[f[y]], da[y], 1, n, 1)), y = up[f[y]];
else marge(x_tot, tot(da[f[x]], da[x], 1, n, 1)), x = up[f[x]];
if (da[x] > da[y]) return swap(y_tot.left, y_tot.right), marge(x_tot, tot(da[y], da[x], 1, n, 1)), marge(x_tot, y_tot), x_tot.tot;
else return swap(x_tot.left, x_tot.right), marge(y_tot, tot(da[x], da[y], 1, n, 1)), marge(y_tot, x_tot), y_tot.tot;
}
void change(int x, int y, int c)
{
while (f[x] != f[y])
if (d[f[x]] < d[f[y]]) cov(da[f[y]], da[y], c, 1, n, 1), y = up[f[y]];
else cov(da[f[x]], da[x], c, 1, n, 1), x = up[f[x]];
if (da[x] > da[y]) swap(x, y);
cov(da[x], da[y], c, 1, n, 1);
}
void add(int x, int y)
{
c[++sg] = y, next[sg] = g[x], g[x] = sg;
c[++sg] = x, next[sg] = g[y], g[y] = sg;
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
n = getint(); m = getint();
for (int i = 1; i <= n; ++i) col[i] = getint() + 1;
for (int i = 1; i < n; ++i)
x = getint(), y = getint(), add(x, y);
sg = 0;
dfs(1); nowp = 1, mak(1, 1); build(1, n, 1);
for (int i = 1; i <= m; ++i)
{
while (ch != 'C' && ch != 'Q') ch = getchar();
if (ch == 'Q') x = getint(), y = getint(), printf("%d\n", query(x, y));
else x = getint(), y = getint(), co = getint(), change(x, y, co + 1);
}
}
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define a p[c[x][0]]
#define b p[c[x][1]]
char ch;
#define add(A, B) cp[++sg] = B, next[sg] = g[A], g[A] = sg
#define gs (ch < '0' || ch > '9')
int getint() { int wis = 0; ch = getchar(); while (gs) ch = getchar(); while (!gs) wis = wis * 10 + ch - '0', ch = getchar(); return wis; }
const int ys = 100010;
using namespace std;
int n, m, x, y, z, q, lap, sg;
int g[ys], next[ys * 2], cp[ys * 2];
int col[ys], pus[ys];
int c[ys][2], w[ys], f[ys];
struct Lek
{
int tot, right, left;
} p[100010], ans, clear;
void update(int x)
{
p[x].tot = a.tot + b.tot - (a.right == col[x]) - (b.left == col[x]) + 1;
p[x].left = !a.left ? col[x] : a.left;
p[x].right = !b.right ? col[x] : b.right;
}
void push(int x)
{
if (pus[x])
pus[c[x][0]] = pus[c[x][1]] = col[c[x][0]] = col[c[x][1]] = pus[x],
p[c[x][0]] = p[c[x][1]] = (Lek){1, pus[x], pus[x]};
pus[x] = 0;
p[0] = clear; pus[0] = col[0] = 0;
}
void rota(int x)
{
int y = f[x], p, q; push(y); push(x);
w[x] = w[y]; p = c[y][1] == x; q = !p;
if (w[y]) c[f[y]][y == c[f[y]][1]] = x; w[y] = 1;
f[x] = f[y]; f[y] = x;
c[y][p] = c[x][q]; f[c[x][q]] = y;
c[x][q] = y;
update(y);
}
void splay(int x)
{
int y, z;
for (; w[x]; rota(x))
if (y = f[x], z = f[y], w[y])
if ((c[y][1] == x) ^ (c[z][1] == y))
rota(y); else rota(x);
push(x); update(x);
}
int access(int u)
{
int v = 0;
for (; u; v = u, u = f[u])
{
splay(u); lap = c[u][1];
if (c[u][1]) w[c[u][1]] = 0; c[u][1] = v;
if (v) f[v] = u, w[v] = 1;
update(u);
}
return v;
}
void dfs(int z)
{
for (int x = g[z]; x; x = next[x])
if (cp[x] != f[z]) f[cp[x]] = z, dfs(cp[x]);
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
n = getint(), m = getint();
for (int i = 1; i <= n; ++i)
col[i] = getint() + 1, p[i] = (Lek){1, col[i], col[i]};
for (int i = 1; i < n; ++i)
x = getint(), y = getint(), add(x, y), add(y, x);
dfs(1);
for (int i = 1; i <= m; ++i)
{
while (ch != 'C' && ch != 'Q') ch = getchar();
if (ch == 'C')
{
x = getint(); y = getint(); z = getint() + 1;
access(x); q = access(y); splay(q);
pus[c[q][1]] = pus[lap] = col[c[q][1]] = col[lap] = col[q] = z;
p[c[q][1]] = p[lap] = (Lek){1, z, z};
update(q);
p[0] = clear; pus[0] = col[0] = 0;
}
else
{
x = getint(); y = getint();
access(x); q = access(y); splay(q);
printf("%d\n", p[lap].tot + 1 + p[c[q][1]].tot - (p[lap].left == col[q]) - (p[c[q][1]].left == col[q]));
}
}
}