题意:一棵树n个结点,每条边有0.1两种权值,每次询问权值为奇数的路径数目,或者改变某一条边的权值。
分析:这个题目很巧妙低利用了异或和的特性,dfs得到每个点到根结点的权值异或和,然后奇数则为1,偶数为0,异或和为0和1的点组成的路径权值和一定为奇数,询问结果就是0个数和1个数乘积2倍。
代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <map> 5 #include <cstring> 6 #include <cmath> 7 #include <algorithm> 8 #include <set> 9 #define pb push_back 10 #define mp make_pair 11 12 #define lson l, m, rt<<1 13 #define rson m+1, r, rt<<1|1 14 #define sz(x) ((int)((x).size())) 15 #define pb push_back 16 #define in freopen("data.txt", "r", stdin); 17 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 18 #define inf 0x0f0f0f0f 19 using namespace std; 20 typedef pair<int, int> PII; 21 typedef map<string, int> MPS; 22 typedef long long LL; 23 24 const int maxn = 30000 + 100; 25 MPS mps; 26 27 struct Edge { 28 int u, v, c; 29 Edge() {} 30 Edge(int u, int v, int c):u(u), v(v), c(c) {} 31 }; 32 vector<Edge> edges; 33 vector<int> g[maxn]; 34 35 int n, m, q, cnt; 36 int le[maxn], ri[maxn]; 37 38 int idx(char *s) { 39 if(mps.count(s) == false) 40 mps[s] = ++cnt; 41 return mps[s]; 42 } 43 44 void add(int u, int v, int c) { 45 edges.pb(Edge(u, v, c)); 46 edges.pb(Edge(v, u, c)); 47 m = edges.size(); 48 g[u].pb(m-2); 49 g[v].pb(m-1); 50 } 51 char sa[20], sb[20]; 52 int cover[maxn<<2], val[maxn], dep[maxn], ans[maxn<<2]; 53 void PushUp(int rt) { 54 ans[rt] = ans[rt<<1]+ans[rt<<1|1]; 55 } 56 //线段树的每个结点要初始化!!!! 57 58 void PushDown(int l, int r, int rt) { 59 int m = (l+r)>>1; 60 if(cover[rt]) { 61 cover[rt<<1] ^= 1; 62 cover[rt<<1|1] ^= 1; 63 ans[rt<<1] = m-l+1-ans[rt<<1]; 64 ans[rt<<1|1] = r-m-ans[rt<<1|1]; 65 cover[rt] = 0; 66 } 67 } 68 void build(int l, int r, int rt) { 69 if(l == r) { 70 cover[rt] = 0; 71 ans[rt] = val[l]; 72 return; 73 } 74 cover[rt] = 0; 75 int m = (l+r)>>1; 76 build(lson); 77 build(rson); 78 PushUp(rt); 79 } 80 void update(int l, int r, int rt, int L, int R) { 81 if(L <= l && R >= r) { 82 cover[rt] ^= 1; 83 ans[rt] = r-l+1-ans[rt]; 84 return; 85 } 86 87 int m = (l+r)>>1; 88 PushDown(l, r, rt); 89 if(L <= m) 90 update(lson, L, R); 91 if(R > m) 92 update(rson, L, R); 93 PushUp(rt); 94 } 95 void dfs(int u, int fa, int va) { 96 dep[u] = dep[fa] + 1; 97 le[u] = ++cnt; 98 val[cnt] = va; 99 for(int i = 0; i < (int)g[u].size(); i++) { 100 Edge e = edges[g[u][i]]; 101 int v = e.v; 102 int c = e.c; 103 if(v == fa) continue; 104 dfs(v, u, c^va); 105 } 106 ri[u] = cnt; 107 } 108 int main() { 109 110 int T; 111 int kase = 0; 112 for(int t = scanf("%d", &T); t <= T; t++) { 113 scanf("%d", &n); 114 mps.clear(); 115 cnt = 0; 116 edges.clear(); 117 for(int i = 1; i <= n; i++) { 118 g[i].clear(); 119 scanf("%s", sa); 120 idx(sa); 121 } 122 for(int i = 0; i < n-1; i++) { 123 int c, u, v; 124 scanf("%s%s%d", sa, sb, &c); 125 u = idx(sa); 126 v = idx(sb); 127 add(u, v, c); 128 } 129 scanf("%d", &q); 130 printf("Case #%d:\n", ++kase); 131 cnt = 0; 132 dfs(1, 0, 0); 133 build(1, n, 1); 134 LL res = 0; 135 while(q--) { 136 scanf("%s", sa); 137 if(sa[0] == ‘Q‘) { 138 res = (LL)(n-ans[1])*ans[1]*2; 139 printf("%I64d\n", res); 140 } else { 141 int x; 142 scanf("%d", &x); 143 x--; 144 x <<= 1; 145 int u = edges[x].u; 146 int v = edges[x].v; 147 if(dep[u] < dep[v]) swap(u, v); 148 update(1, n, 1, le[u], ri[u]); 149 } 150 } 151 } 152 return 0; 153 }
当然也有一种更复杂的方法,同Qtree4,可以拿来练手,感觉有点无聊。
原文:http://www.cnblogs.com/rootial/p/4047012.html