首页 > 代码库 > BZOJ2870 最长道路tree
BZOJ2870 最长道路tree
ZKY:"如果把分治过程记录下来就可以做到动态修改询问,不过好像没人给这种数据结构起名字(或者我太弱了不知道)……我就给它起名叫点分树了……"
结果什么是"点分树"蒟蒻还是没有搞懂= =Orz
这题就是先点分治,然后暴力求出子树里面所有的链。但是合并两个子树的链。。。有点,不太科学
于是做法是把子树分成两部分,穿过这两个部分的所有链的答案,然后递归这两部分子树。
恩很好。。。于是敲了起来,最后竟然调了2h,错因是。。。
树的重心求错了
我还是滚回PJ组玩泥巴算了。。。
1 /************************************************************** 2 Problem: 2870 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1032 ms 7 Memory:6596 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 typedef long long ll; 15 const int N = 50005; 16 17 struct edge { 18 int next, to; 19 edge() {} 20 edge(int _n, int _t) : next(_n), to(_t) {} 21 } e[N << 1]; 22 int first[N], tot; 23 24 struct data { 25 int l, v; 26 data() {} 27 data(int _l, int _v) : l(_l), v(_v) {} 28 29 inline bool operator < (const data &x) const { 30 return l < x.l; 31 } 32 } t1[N], t2[N]; 33 int cnt_t1, cnt_t2; 34 35 struct tree_node { 36 int sz, w, vis; 37 } tr[N]; 38 39 ll ans; 40 int n, now; 41 int q1[N], q2[N], top1, top2; 42 43 inline int read() { 44 int x = 0; 45 char ch = getchar(); 46 while (ch < ‘0‘ || ‘9‘ < ch) 47 ch = getchar(); 48 while (‘0‘ <= ch && ch <= ‘9‘) { 49 x = x * 10 + ch - ‘0‘; 50 ch = getchar(); 51 } 52 return x; 53 } 54 55 inline void Add_Edges(int x, int y) { 56 e[++tot] = edge(first[x], y), first[x] = tot; 57 e[++tot] = edge(first[y], x), first[y] = tot; 58 } 59 60 int Maxsz, Root; 61 62 void dfs(int p, int fa, int sz) { 63 int x, y, maxsz = 0; 64 tr[p].sz = 1; 65 for (x = first[p]; x; x = e[x].next) 66 if ((y = e[x].to) != fa && !tr[y].vis) { 67 dfs(y, p, sz); 68 tr[p].sz += tr[y].sz; 69 maxsz = max(maxsz, tr[y].sz); 70 } 71 maxsz = max(maxsz, sz - tr[p].sz); 72 if (maxsz < Maxsz) 73 Root = p, Maxsz = maxsz; 74 } 75 76 int find_root(int p, int sz) { 77 Maxsz = N << 1; 78 dfs(p, 0, sz); 79 return Root; 80 } 81 82 void count_sz(int p, int fa) { 83 int x, y; 84 tr[p].sz = 1; 85 for (x = first[p]; x; x = e[x].next) 86 if ((y = e[x].to) != fa && !tr[y].vis) { 87 count_sz(y, p); 88 tr[p].sz += tr[y].sz; 89 } 90 } 91 92 void count1(int p, int fa, int len, int v) { 93 int x, y; 94 t1[++cnt_t1] = data(len, v); 95 for (x = first[p]; x; x = e[x].next) 96 if ((y = e[x].to) != fa && !tr[y].vis) 97 count1(y, p, len + 1, min(v, tr[y].w)); 98 } 99 100 void count2(int p, int fa, int len, int v) {101 int x, y;102 t2[++cnt_t2] = data(len, v);103 for (x = first[p]; x; x = e[x].next)104 if ((y = e[x].to) != fa && !tr[y].vis)105 count2(y, p, len + 1, min(v, tr[y].w));106 }107 108 void count(int p, int first_p) {109 int x, y;110 t1[++cnt_t1] = data(1, tr[p].w);111 for (x = first[p]; x != first_p; x = e[x].next)112 if (!tr[y = e[x].to].vis)113 count1(y, p, 2, min(tr[p].w, tr[y].w));114 t2[++cnt_t2] = data(1, tr[p].w);115 for (x = first_p; x; x = e[x].next)116 if (!tr[y = e[x].to].vis)117 count2(y, p, 2, min(tr[p].w, tr[y].w));118 }119 120 void work(int p, int cnt_p) {121 int root = find_root(p, cnt_p), sz1 = 0, sz2 = 0, tmp;122 int x, y, first_root, i, l1, l2;123 count_sz(root, 0);124 for (x = first[root]; x; x = e[x].next)125 if (!tr[y = e[x].to].vis) {126 sz1 += tr[y].sz;127 if (sz1 + 1 << 1 >= tr[root].sz) {128 first_root = e[x].next;129 sz2 = tr[root].sz - (sz1++);130 break;131 }132 }133 cnt_t1 = cnt_t2 = 0;134 count(root, first_root);135 136 sort(t1 + 1, t1 + cnt_t1 + 1), sort(t2 + 1, t2 + cnt_t2 + 1);137 for (i = 1, top1 = 0; i <= cnt_t1; ++i) {138 while (top1 && t1[i].v > t1[q1[top1]].v) --top1;139 q1[++top1] = i;140 }141 for (i = 1, top2 = 0; i <= cnt_t2; ++i) {142 while (top2 && t2[i].v > t2[q2[top2]].v) --top2;143 q2[++top2] = i;144 }145 146 for (l1 = 1, l2 = 0; l1 <= top1; ++l1) {147 while (l2 < top2 && t2[q2[l2 + 1]].v >= t1[q1[l1]].v) ++l2;148 ans = max(ans, (ll) (t1[q1[l1]].l + t2[q2[l2]].l - 1) * t1[q1[l1]].v);149 }150 for (l1 = 0, l2 = 1; l2 <= top2; ++l2) {151 while (l1 < top1 && t1[q1[l1 + 1]].v >= t2[q2[l2]].v) ++l1;152 ans = max(ans, (ll) (t1[q1[l1]].l + t2[q2[l2]].l - 1) * t2[q2[l2]].v);153 }154 155 tmp = ++now;156 if (sz2 - 1 >= 2) {157 for (x = first[root]; x != first_root; x = e[x].next)158 if (!tr[y = e[x].to].vis)159 tr[y].vis = now;160 work(root, sz2);161 for (x = first[root]; x != first_root; x = e[x].next)162 if (tr[y = e[x].to].vis == tmp)163 tr[y].vis = 0;164 }165 tmp = ++now;166 if (sz1 - 1 >= 2) {167 for (x = first_root; x; x = e[x].next)168 if (!tr[y = e[x].to].vis)169 tr[y].vis = now;170 work(root, sz1);171 for (x = first_root; x; x = e[x].next)172 if (tr[y = e[x].to].vis == tmp)173 tr[y].vis = 0;174 }175 }176 177 int main() {178 int i;179 n = read();180 for (i = 1; i <= n; ++i)181 tr[i].w = read();182 for (i = 1; i < n; ++i)183 Add_Edges(read(), read());184 work(1, n);185 printf("%lld\n", ans);186 return 0;187 }
BZOJ2870 最长道路tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。