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 }

时间: 2024-10-12 19:44:10

BZOJ2870 最长道路tree的相关文章

【BZOJ2870】最长道路tree 点分治+树状数组

[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都有一个拥挤程度v[i],我们认为从路口s走到路口t的痛苦程度为s到t的路径上拥挤程度的最小值,乘上这条路径上的路口个数所得的积.现在请你求出痛苦程度最大的一条路径,你只需输出这个痛苦程度. 简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积

POJ 2485 Prim 找最长的边

A国没有高速公路,因此A国的交通很困难.政府意识到了这个问题并且计划建造一些高速公路,以至于可以在不离开高速公路的情况下在任意两座城镇之间行驶. A国的城镇编号为1到N, 每条高速公路连接这两个城镇,所有高速公路都可以在两个方向上使用.高速公路可以自由的相互交叉. A国政府希望尽量减少最长高速公路的建设时间(使建设的最长的高速公路最短),但是他们要保证每个城镇都可以通过高速公路到达任意一座城镇. Input 第一个输入的数字T,代表着T组样例. 接下来输入一个N, 代表一共有N个城镇. 然后读入

融合应用11.1.8安装,一步一步的引导

融合应用11.1.8安装,一步一步的引导 融合应用11.1.8 安装并不是简单的与电子商务套件11 i / R12安装. 所以我们需要安装划分为许多步骤. 请注意,11.1.8 11.1.7总统发布供应是几乎相同的. 在同一时间的步骤和一些组件11.1.6和11.1.5相比有所不同. 这里我们有实际使用同一个11.1.7步骤在这里11.1.8指导和将提到11.1.7相比无论我们看到一个不同的步骤. 注意:如果您正在寻找融合应用程序 11.1.6 安装步骤,那么你可以参考以下链接. http://

P2680 运输计划

题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物 流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰. 为了鼓励科技创新,L 国国王同意小 P 的

C 封装一个简单二叉树基库

引文 今天分享一个喜欢佩服的伟人,应该算人类文明极大突破者.收藏过一张纸币类型如下 那我们继续科普一段关于他的简介 '高斯有些孤傲,但令人惊奇的是,他春风得意地度过了中产阶级的一生,而  没有遭受到冷酷现实的打击:这种打击常无情地加诸于每个脱离现实环境生活的  人.或许高斯讲求实效和追求完美的性格,有助于让他抓住生活中的简单现实.  高斯22岁获博士学位,25岁当选圣彼德堡科学院外籍院士,30岁任哥廷根大学数  学教授兼天文台台长.虽说高斯不喜欢浮华荣耀,但在他成名后的五十年间,这  些东西就像

1682: [Usaco2005 Mar]Out of Hay 干草危机

1682: [Usaco2005 Mar]Out of Hay 干草危机 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 391  Solved: 258[Submit][Status] Description The cows have run out of hay, a horrible event that must be remedied immediately. Bessie intends to visit the other farms

51 nod 1427 文明 (并查集 + 树的直径)

1427 文明 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 安德鲁在玩一个叫“文明”的游戏.大妈正在帮助他. 这个游戏里面有n个城市和m条双向的道路.城市从1到n编号.对于每一对城市,他们之间要么有唯一的一条道路,要么就是不可互达.一条道路的定义是一个包含不同城市的序列 v1, v2,...,vk ,  vi  和  vi+1 (1≤ i < k)之间有直接的一条道路相连.这条道路的长度是k-1.两个城市在同一区域的

ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TshingHua OJ-旅行商TSP)

做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -|| 旅行商(TSP) Description Shrek is a postman working in the mountain, whose routine work is sending mail to n villages. Unfortunately, road between villages is

【图】拓扑排序

参考CSDN拓扑排序的原理及Java实现 拓扑排序C++实现 拓扑排序百度百科 若不是上了学堂在线的数据结构课程,我估计今后不做技术的话,都接触不到图的拓扑排序这个概念了.先是看了百度百科的解释,拓扑排序现实中的应用是选课,即某些课程需要一些先修课程的学习后才适合上.比如数据结构的学习,是离散数学.编程语言,后者是前者的先修课程. 拓扑排序定义:将有向无环图DAG中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 1.创建图: