首页 > 代码库 > BZOJ3697 采药人的路径
BZOJ3697 采药人的路径
点分治。。。尼玛啊!蒟蒻怎么做的那么桑心%>_<%
Orz hzwer
蒟蒻就补充一下hzwer没讲的东西:
(1)对于阴性的植物权值设为-1,阳性的设为+1
(2)最后一段就是讲如何利用新的子树的f[]值求出ans和更新g[]
1 /************************************************************** 2 Problem: 3697 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1752 ms 7 Memory:15924 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 100005; 15 16 struct edge { 17 int next, to, v; 18 edge() {} 19 edge(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {} 20 } e[N << 1]; 21 22 int first[N], tot; 23 24 struct tree_node { 25 int sz, dep, dis; 26 bool vis; 27 } tr[N]; 28 29 int n, k; 30 int cnt[N << 1]; 31 long long f[N << 1][2], g[N << 1][2], ans; 32 int Root, Maxsz; 33 int mx_dep, mx; 34 35 inline int read() { 36 int x = 0; 37 char ch = getchar(); 38 while (ch < ‘0‘ || ‘9‘ < ch) 39 ch = getchar(); 40 while (‘0‘ <= ch && ch <= ‘9‘) { 41 x = x * 10 + ch - ‘0‘; 42 ch = getchar(); 43 } 44 return x; 45 } 46 47 void Add_Edges(int x, int y, int z) { 48 e[++tot] = edge(first[x], y, z), first[x] = tot; 49 e[++tot] = edge(first[y], x, z), first[y] = tot; 50 } 51 52 void dfs(int p, int fa, int sz) { 53 int x, y, maxsz = 0; 54 tr[p].sz = 1; 55 for (x = first[p]; x; x = e[x].next) 56 if ((y = e[x].to) != fa && !tr[y].vis) { 57 dfs(y, p, sz); 58 tr[p].sz += tr[y].sz; 59 maxsz = max(maxsz, tr[y].sz); 60 } 61 maxsz = max(maxsz, sz - tr[p].sz); 62 if (maxsz < Maxsz) 63 Root = p, Maxsz = maxsz; 64 } 65 66 int get_root(int p, int sz) { 67 Maxsz = N << 1; 68 dfs(p, 0, sz); 69 return Root; 70 } 71 72 void Dfs(int p, int fa) { 73 int x, y; 74 mx_dep = max(mx_dep, tr[p].dep); 75 if (cnt[tr[p].dis]) ++f[tr[p].dis][1]; 76 else ++f[tr[p].dis][0]; 77 ++cnt[tr[p].dis]; 78 for (x = first[p]; x; x = e[x].next) 79 if ((y = e[x].to) != fa && !tr[y].vis) { 80 tr[y].dep = tr[p].dep + 1, tr[y].dis = tr[p].dis + e[x].v; 81 Dfs(y, p); 82 } 83 --cnt[tr[p].dis]; 84 } 85 86 void cal(int p) { 87 int x, y, j; 88 mx = 0, g[n][0] = 1; 89 for (x = first[p]; x; x = e[x].next) 90 if (!tr[y = e[x].to].vis) { 91 tr[y].dis = n + e[x].v, tr[y].dep = 1, mx_dep = 1; 92 Dfs(y, p); 93 mx = max(mx, mx_dep); 94 ans += (g[n][0] - 1) * f[n][0]; 95 for (j = -mx_dep; j <= mx_dep; ++j) 96 ans += g[n - j][1] * f[n + j][1] + g[n - j][0] * f[n + j][1] + g[n - j][1] * f[n + j][0]; 97 for (j = n - mx_dep; j <= n + mx_dep; ++j) { 98 g[j][0] += f[j][0], g[j][1] += f[j][1]; 99 f[j][0] = f[j][1] = 0;100 }101 }102 for (j = n - mx; j <= n + mx; ++j)103 g[j][0] = g[j][1] = 0;104 }105 106 void work(int p, int sz) {107 int root = get_root(p, sz), x, y;108 tr[root].vis = 1;109 cal(root);110 for (x = first[root]; x; x = e[x].next)111 if (!tr[y = e[x].to].vis)112 work(y, tr[y].sz);113 }114 115 int main() {116 int i, x, y, z;117 n = read();118 for (i = 1; i < n; ++i) {119 x = read(), y = read(), z = read();120 Add_Edges(x, y, z ? 1 : -1);121 }122 work(1, n);123 printf("%lld\n", ans);124 return 0;125 }
(其实我觉得吧。。。点分治做到1600ms是极限了,rank最前面的两位应该用了特殊的技♂巧)
BZOJ3697 采药人的路径
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。