题目
http://acm.hdu.edu.cn/showproblem.php?pid=5039
分析
DFS序+线段树
由于异或运算的特殊性,两点间的异或值等于两点到根的异或值的异或
所以答案为到根的异或值为1的点数*到根的异或值为0的点数*2
线段树维护DFS序维护区间和即可
代码
/************************************************** * Problem: HDU 5039 * Author: clavichord93 * State: Accepted **************************************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> using namespace std; const int MAX_E = 60005; const int MAX_N = 30005; struct Edge { int dest; int id; int cost; Edge *next; Edge() {} Edge(int _dest, int _id, int _cost, Edge *_next) : dest(_dest), id(_id), cost(_cost), next(_next) {} }; Edge EdgePool[MAX_E]; Edge *EP; Edge *e[MAX_N]; int n; map<string, int> name; char s[100]; char t[100]; int ind; int st[MAX_N]; int en[MAX_N]; int seq[MAX_N]; int value[MAX_N]; int next[MAX_N]; int sum[MAX_N << 2]; bool tag[MAX_N << 2]; inline void addedge(int a, int b, int c, int id) { e[a] = new(EP++)Edge(b, id, c, e[a]); e[b] = new(EP++)Edge(a, id, c, e[b]); } void dfs(int i, int parent) { st[i] = ++ind; seq[ind] = i; for (Edge *j = e[i]; j; j = j->next) { if (j->dest != parent) { next[j->id] = j->dest; value[j->dest] = value[i] ^ j->cost; dfs(j->dest, i); } } en[i] = ind; } #define lch(t) (t << 1) #define rch(t) (t << 1 | 1) void makeTree(int t, int l, int r) { if (l == r) { sum[t] = value[seq[l]]; tag[t] = 0; } else { int mid = (l + r) >> 1; makeTree(lch(t), l, mid); makeTree(rch(t), mid + 1, r); sum[t] = sum[lch(t)] + sum[rch(t)]; tag[t] = 0; } } void pushdown(int t, int l, int r) { if (tag[t]) { int lt = lch(t); int rt = rch(t); int mid = (l + r) >> 1; sum[lt] = mid - l + 1 - sum[lt]; tag[lt] ^= 1; sum[rt] = r - mid - sum[rt]; tag[rt] ^= 1; tag[t] = 0; } } void reverse(int t, int l, int r, int x, int y) { if (x <= l && r <= y) { sum[t] = r - l + 1 - sum[t]; tag[t] ^= 1; } else { pushdown(t, l, r); int mid = (l + r) >> 1; if (x <= mid) { reverse(lch(t), l, mid, x, y); } if (y > mid) { reverse(rch(t), mid + 1, r, x, y); } sum[t] = sum[lch(t)] + sum[rch(t)]; } } #undef lch #undef rch int main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); #endif int T; scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { EP = EdgePool; memset(e, 0, sizeof(e)); name.clear(); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", s); string t(s); name[t] = i; } for (int i = 1; i < n; i++) { int val; scanf("%s %s %d", s, t, &val); string a(s); string b(t); int u = name[a]; int v = name[b]; addedge(u, v, val, i); } ind = 0; memset(st, 0, sizeof(st)); memset(en, 0, sizeof(en)); memset(seq, 0, sizeof(seq)); memset(value, 0, sizeof(value)); memset(next, 0, sizeof(next)); dfs(1, 0); makeTree(1, 1, n); int m; scanf("%d", &m); printf("Case #%d:\n", cas); for (int i = 0; i < m; i++) { scanf("%s", s); if (s[0] == 'M') { int x; scanf("%d", &x); x = next[x]; reverse(1, 1, n, st[x], en[x]); } else { printf("%I64d\n", (long long)sum[1] * (n - sum[1]) * 2); } } } return 0; }