- 题意:
给n个点(1-n)的树,1为根节点,每个点初始值为1。q次操作:1、C操作:每次给一个标号x,将x节点的值取非 2、Q操作:给x,求x子树的点值之和 - 分析:
这个题目关键在于将树上的节点放到一维来处理,这样就可以用树状数组或者线段树来解决了。处理时使用dfs,对每个节点都进行编号。
树状数组:
const int MAXN = 100001; int nxt[MAXN << 1], val[MAXN << 1], head[MAXN], tot = 0; void adj_init(int n) { REP(i, n) head[i] = -1; tot = 0; } void adj_ins(int u, int v) { val[tot] = v; nxt[tot] = head[u]; head[u] = tot++; } int dfs_clock; int lft[MAXN], rht[MAXN]; void dfs(int u, int fa) { lft[u] = dfs_clock++; for (int i = head[u]; ~i; i = nxt[i]) { if (val[i] != fa) dfs(val[i], u); } rht[u] = dfs_clock - 1; } int tree[MAXN]; inline int lowbit(int x) { return x & (-x); } inline void add(int p, int v) { for (; p < MAXN; p += lowbit(p)) tree[p] += v; } inline int sum(int p) { int ret = 0; for (; p > 0; p -= lowbit(p)) ret += tree[p]; return ret; } int ipt[MAXN]; int main() { int n, q; while (~RI(n)) { adj_init(n + 1); dfs_clock = 1; CLR(tree, 0); FE(i, 1, n) ipt[i] = 1; REP(i, n - 1) { int a, b; RII(a, b); adj_ins(a, b); adj_ins(b, a); } dfs(1, -1); RI(q); FE(kase, 1, q) { char op; int v; scanf(" %c %d", &op, &v); int l = lft[v], r = rht[v]; if (op == 'Q') { WI(r - l + 1 - sum(r) + sum(l - 1)); } else { int ad = 1; if (ipt[v] == 0) ad = -1; ipt[v] ^= 1; add(l, ad); } } } return 0; }
const int MAXN = 100001; int nxt[MAXN << 1], val[MAXN << 1], head[MAXN], tot = 0; void adj_init(int n) { REP(i, n) head[i] = -1; tot = 0; } void adj_ins(int u, int v) { val[tot] = v; nxt[tot] = head[u]; head[u] = tot++; } int dfs_clock; int lft[MAXN], rht[MAXN]; void dfs(int u, int fa) { lft[u] = dfs_clock++; for (int i = head[u]; ~i; i = nxt[i]) { if (val[i] != fa) dfs(val[i], u); } rht[u] = dfs_clock - 1; } #define lson rt << 1 #define rson rt << 1 | 1 struct Node { int l, r, m; int sum; } nd[MAXN << 2]; void pushUP(int rt) { nd[rt].sum = nd[lson].sum + nd[rson].sum; } void build(int l, int r, int rt) { nd[rt].l = l; nd[rt].r = r; nd[rt].m = (l + r) >> 1; if (l == r) nd[rt].sum = 1; else { build(l, nd[rt].m, lson); build(nd[rt].m + 1, r, rson); pushUP(rt); } } void add(int p, int v, int rt) { if (nd[rt].l == nd[rt].r) nd[rt].sum += v; else { if (p <= nd[rt].m) add(p, v, lson); else add(p, v, rson); pushUP(rt); } } int query(int L, int R, int rt) { if (L <= nd[rt].l && nd[rt].r <= R) return nd[rt].sum; else { int ret = 0; if (L <= nd[rt].m) ret += query(L, R, lson); if (R > nd[rt].m) ret += query(L, R, rson); return ret; } } int ipt[MAXN]; int main() { int n, q; while (~RI(n)) { adj_init(n + 1); dfs_clock = 1; build(1, n, 1); FE(i, 1, n) ipt[i] = 1; REP(i, n - 1) { int a, b; RII(a, b); adj_ins(a, b); adj_ins(b, a); } dfs(1, -1); RI(q); FE(kase, 1, q) { char op; int p; scanf(" %c %d", &op, &p); int l = lft[p], r = rht[p]; if (op == 'Q') { WI(query(l, r, 1)); } else { int ad = -1; if (ipt[p] == 0) ad = 1; ipt[p] ^= 1; add(l, ad, 1); } } } return 0; }