Decsripiton:
给出一棵
n
n
个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为。
定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目。
现有
m
m
次操作,每次为一下三种之一:
:对
x
x
执行一次感染;
:把根节点改为
x
x
,并对原来的根节点执行一次感染;
:询问
x
x
子树中所有节点感染代价的平均值。
Solution:
这些操作和有关,第一个操作是
access
a
c
c
e
s
s
,第二个操作跟轻重边有关,其实一个点的权值就是一个点到根的轻边的数量,那么考虑
access
a
c
c
e
s
s
的时候切换轻重边时更新子树。每次更新时要找到上一个
splay
s
p
l
a
y
的最浅点,因为我们要更新的点在那棵
splay
s
p
l
a
y
里,那么跟当前点连接的肯定是里面的最浅点。第三个操作查询子树即可。
有一个细节是刚开始的时候直接把所有点的父亲初始化就可以了。
这是一份过不了的代码,交了别人的代码。垃圾卡常出题人。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
inline int read() {
int x = 0, f = 1;
char c = getchar();
while(!isdigit(c)) {
if(c == '-') {
f = -1;
}
c = getchar();
}
while(isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
namespace tr {
struct edge {
int nxt, to;
} e[maxn * 2];
int dfs_clock, rt, cnt;
long long t1[maxn], t2[maxn];
int Log[maxn], h[maxn], fa[maxn][21], mir[maxn], val[maxn], in[maxn], out[maxn];
inline void link(int u, int v) {
e[++cnt].nxt = h[u];
h[u] = cnt;
e[cnt].to = v;
}
void dfs(int u, int last) {
in[u] = ++dfs_clock;
mir[in[u]] = u;
for(int i = h[u]; i; i = e[i].nxt) {
if(e[i].to == last) {
continue;
}
fa[e[i].to][0] = u;
val[e[i].to] = val[u] + 1;
dfs(e[i].to, u);
}
out[u] = dfs_clock;
}
inline void add(int x, int d) {
long long p = x;
for(; x <= n; x += x & -x) {
t1[x] += d;
t2[x] += p * d;
}
}
inline long long Ask(int x) {
long long s1 = 0, s2 = 0, p = x;
for(; x; x -= x & -x) {
s1 += t1[x];
s2 += t2[x];
}
return (p + 1) * s1 - s2;
}
inline void update(int l, int r, int d) {
if(l > r) {
return;
}
add(r + 1, -d);
add(l, d);
}
inline int query(int l, int r) {
if(l > r) {
return 0;
}
return Ask(r) - Ask(l - 1);
}
void change(int x, int d) {
if(rt == x) {
update(1, n, d);
} else if(in[rt] > in[x] && out[rt] < out[x]) {
int p = rt;
for(int i = Log[val[rt] - val[x]] ; ~i; --i) {
if(val[fa[p][i]] > val[x]) {
p = fa[p][i];
}
}
if(in[p] > 1) {
update(1, in[p] - 1, d);
}
if(out[p] < n) {
update(out[p] + 1, n, d);
}
} else {
update(in[x], out[x], d);
}
}
} using namespace tr;
namespace lct {
struct node {
int f, rev;
int ch[2];
} t[maxn];
inline int wh(int x) {
return x == t[t[x].f].ch[1];
}
inline bool isr(int x) {
return !t[x].f || (t[t[x].f].ch[0] != x && t[t[x].f].ch[1] != x);
}
inline void paint(int x) {
t[x].rev ^= 1;
swap(t[x].ch[0], t[x].ch[1]);
}
inline void pushdown(int x) {
if(t[x].rev) {
paint(t[x].ch[0]);
paint(t[x].ch[1]);
t[x].rev = 0;
}
}
inline void pd(int x) {
if(!isr(x)) {
pd(t[x].f);
}
pushdown(x);
}
void rotate(int x) {
int y = t[x].f, z = t[y].f, w = wh(x);
if(!isr(y)) {
t[z].ch[wh(y)] = x;
}
t[x].f = z;
t[y].f = x;
t[t[x].ch[w ^ 1]].f = y;
t[y].ch[w] = t[x].ch[w ^ 1];
t[x].ch[w ^ 1] = y;
}
inline void splay(int x) {
pd(x);
for(; !isr(x); rotate(x)) {
if(wh(x) == wh(t[x].f)) {
rotate(wh(x) == wh(t[x].f) ? t[x].f : x);
}
}
}
inline int findlow(int x) {
splay(x);
for(pushdown(x); t[x].ch[0]; x = t[x].ch[0], pushdown(x));
return x;
}
inline void access(int x) {
for(int y = 0, p; x; y = x, x = t[x].f) {
splay(x);
if(t[x].ch[1]) {
p = t[x].ch[1];
t[x].ch[1] = 0;
change(findlow(p), 1);
}
if(y) {
change(findlow(y), -1);
}
t[x].ch[1] = y;
}
}
inline void makert(int x) {
access(x);
splay(x);
paint(x);
rt = x;
}
inline double ask(int x) {
if(rt == x) {
return Ask(n) / (double)n;
} else if(in[rt] > in[x] && out[rt] < out[x]) {
int p = rt;
for(int j = Log[val[rt] - val[x]]; ~j; --j) {
if(val[fa[p][j]] > val[x]) {
p = fa[p][j];
}
}
return (Ask(n) - query(in[p], out[p])) / (double)(n - out[p] + in[p] - 1);
} else {
return (query(in[x], out[x])) / (double)(out[x] - in[x] + 1);
}
}
}
int main() {
n = read();
m = read();
for(int i = 1; i < n; ++i) {
int u = read(), v = read();
link(u, v);
link(v, u);
}
val[1] = 1;
dfs(rt = 1, 0);
for(int j = 1; j <= 20; ++j) {
for(int i = 1; i <= n; ++i) {
fa[i][j] = fa[fa[i][j - 1]][j - 1];
}
}
for(int i = 2; i <= n; ++i) {
Log[i] = Log[i >> 1] + 1;
}
for(int i = 1; i <= n; ++i) {
add(i, val[mir[i]] - val[mir[i - 1]]);
lct::t[i].f = fa[i][0];
}
while(m--) {
char opt[10];
scanf("%s", opt);
int x = read();
if(opt[2] == 'L') {
lct::access(x);
} else if(opt[2] == 'C') {
lct::makert(x);
} else {
printf("%.10f\n", lct::ask(x));
}
}
return 0;
}