BZOJ 1103
-
题目
-
分析
考虑树链剖分
本题考虑边的个数,而不是点的个数。但是可以考虑用点权代替边权, n n n 个点会有 n − 1 n - 1 n−1 条边,所以在操作时只考虑 n − 1 n - 1 n−1 个点即可。
-
代码
const int N = 250005; int head[N], ver[N], Next[N]; int d[N], son[N], fa[N], cnt, top[N], id[N]; int tot, n, m, r; void add(int x, int y) { ver[++tot] = y; Next[tot] = head[x]; head[x] = tot; } struct stree { int sum; int add; } tree[N << 2]; inline void pushup(int rt) { tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum; } inline void pushdown(int rt,int k) { if (tree[rt].add != -1) { tree[rt << 1].sum = tree[rt].add * (k - (k >> 1)); tree[rt << 1 | 1].sum = tree[rt].add * (k >> 1); tree[rt << 1].add = tree[rt].add; tree[rt << 1 | 1].add = tree[rt].add; tree[rt].add = -1; } } inline void build(int rt, int l, int r) { tree[rt].add = -1; if (l == r) { tree[rt].sum = 1; return; } int mid = (l + r) >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); pushup(rt); } inline void update(int rt, int L, int R, int l, int r ,int val) { if (L <= l && r <= R) { tree[rt].sum = (ll)val * (r - l + 1); tree[rt].add = val; return ; } int mid = (l + r) >> 1; pushdown(rt,r - l + 1); if (L <= mid) update(rt << 1, L, R,l,mid ,val); if (R > mid) update(rt << 1 | 1, L, R, mid + 1,r,val); pushup(rt); } inline int query(int rt, int L, int R, int l, int r) { if (L <= l && r <= R) return tree[rt].sum; int mid = (l + r) >> 1; pushdown(rt,r - l + 1); int ans = 0; if (L <= mid) ans = ans + query(rt << 1, L, R,l,mid); if (R > mid) ans = ans + query(rt << 1 | 1, L, R,mid + 1,r); return ans; } inline void dfs1(int x) { id[x] = 1, d[x] = d[fa[x]] + 1; for (int v, i = head[x]; i; i = Next[i]) if ((v = ver[i]) != fa[x]) { fa[v] = x, dfs1(v), id[x] += id[v]; if (id[son[x]] < id[v]) son[x] = v; } } inline void dfs2(int u, int t) { top[u] = t; id[u] = ++cnt; if (!son[u]) return; dfs2(son[u], t); for (int i = head[u]; i; i = Next[i]) { int v = ver[i]; if (v != son[u] && v != fa[u]) dfs2(v, v); } } inline int sum(int x, int y) { int ret = 0; while (top[x] != top[y]) { if (d[top[x]] < d[top[y]]) swap(x, y); ret += query(1, id[top[x]], id[x], 1, n); x = fa[top[x]]; } if (id[x] > id[y]) swap(x, y); return ret + query(1, id[x] + 1, id[y], 1, n); } inline void change(int x, int y, int c) { while (top[x] != top[y]) { if (d[top[x]] < d[top[y]]) swap(x, y); update(1, id[top[x]], id[x], 1, n, c); x = fa[top[x]]; } if (id[x] > id[y]) swap(x, y); update(1, id[x] + 1, id[y], 1, n, c); } int main () { //freopen("input.in", "r", stdin); //freopen("test.out", "w", stdout); read(n); for (int i = 1; i < n; i++) { int u, v; read(u); read(v); add(u, v); } read(m); build(1, 1, n); dfs1(1); memset(id, 0, sizeof(id)); dfs2(1, 1); for (int i = 1; i <= n + m - 1; i++) { char s[22]; scanf("%s", s); if (s[0] == 'W') { int x; read(x); printf("%d\n", sum(1, x)); } else { int x, y; read(x); read(y); change(x, y, 0); } } return 0 ; }
-
题型
树链剖分