首页 > 代码库 > HDU 5039 Hilarity

HDU 5039 Hilarity

题意:一棵树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 }
View Code

 当然也有一种更复杂的方法,同Qtree4,可以拿来练手,感觉有点无聊。

HDU 5039 Hilarity