HDU 5039 Hilarity

来源:互联网 发布:航天税控发票软件 编辑:程序博客网 时间:2024/06/13 23:42

题意:

一棵树上有些边是1有些是0  问  有几条简单路径路过奇数个1  树上的边的1和0可以修改

思路:

不会做…  看题解才找到思路… TAT

首先要明确一点  对于u->v这条路径  它的奇偶是可以通过root->u和root->v计算的  因为如果从root出发的两路径不相交  那么两路径上的1相加即可判断u->v  如果相交  假设相交部分有x个1  那么对于u->v的1的个数即为两路径相加  再减去2x  很明显减2x不影响奇偶性  因此本题可以得出结论  如果从root出发有y个奇数路径  则答案为 y*((n-1)-y+1) = y*(n-y)  式子中用(n-1)是因为不算root  后面+1是因为奇数路径可以直接当答案不与偶数路径拼接

知道了如何求答案  再来想如何维护边修改  我们发现  修改一条边fu->fv  只影响fv子树中的奇偶性  那么可以用dfs序表示出树的线性结构  再通过线段树区间更新来达到目的

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<cassert>#include<vector>#include<set>#include<map>#include<queue>using namespace std;typedef long long LL;#define N 30010#define L(x) (x<<1)#define R(x) ((x<<1)|1)#define MI(x,y) ((x+y)>>1)int T, t, n, m, tot, idx;int head[N], l[N], r[N], val[N];struct edge {int u, v, flag, next;} ed[N * 2];map<string, int> hash;struct tree {int l, r, odd, lazy;} d[N * 4];void add(int u, int v, int f) {ed[tot].u = u;ed[tot].v = v;ed[tot].flag = f;ed[tot].next = head[u];head[u] = tot++;}void dfs(int u, int f, int fa) {idx++;val[idx] = f;l[u] = idx;for (int i = head[u]; ~i; i = ed[i].next) {if (ed[i].v != fa)dfs(ed[i].v, f ^ ed[i].flag, u);}r[u] = idx;}void down(int i) {if (d[i].lazy) {d[L(i)].lazy ^= 1;d[R(i)].lazy ^= 1;d[L(i)].odd = d[L(i)].r - d[L(i)].l + 1 - d[L(i)].odd;d[R(i)].odd = d[R(i)].r - d[R(i)].l + 1 - d[R(i)].odd;d[i].lazy = 0;}}void up(int i) {d[i].odd = d[L(i)].odd + d[R(i)].odd;}void init(int l, int r, int i) {d[i].l = l;d[i].r = r;d[i].lazy = 0;d[i].odd = val[l];if (l == r)return;int mid = MI(l,r);init(l, mid, L(i));init(mid + 1, r, R(i));up(i);}void update(int l, int r, int i) {if (d[i].l == l && d[i].r == r) {d[i].odd = d[i].r - d[i].l + 1 - d[i].odd;d[i].lazy ^= 1;return;}down(i);int mid = MI(d[i].l,d[i].r);if (r <= mid)update(l, r, L(i));else if (l > mid)update(l, r, R(i));else {update(l, mid, L(i));update(mid + 1, r, R(i));}up(i);}int main() {int i, u, v, f;char str[50], uu[50], vv[50];scanf("%d", &T);for (t = 1; t <= T; t++) {printf("Case #%d:\n", t);hash.clear();scanf("%d", &n);for (i = 1; i <= n; i++) {scanf("%s", str);hash[string(str)] = i;head[i] = -1;}tot = 0;for (i = 1; i < n; i++) {scanf("%s%s%d", uu, vv, &f);u = hash[string(uu)];v = hash[string(vv)];add(u, v, f);add(v, u, f);}idx = 0;dfs(1, 0, 0);init(1, n, 1);scanf("%d", &m);while (m--) {scanf("%s", str);if (str[0] == 'Q')printf("%d\n", d[1].odd * (n - d[1].odd) * 2);else {scanf("%d", &f);f = (f - 1) * 2;u = ed[f].u;v = ed[f].v;if (l[u] > l[v])update(l[u], r[u], 1);elseupdate(l[v], r[v], 1);}}}return 0;}


0 0