首页 > 代码库 > HDU 5039 Hilarity
HDU 5039 Hilarity
题意:
一棵树上有些边是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); else update(l[v], r[v], 1); } } } return 0; }
HDU 5039 Hilarity
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。