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 }
View Code

 

posted on 2014-12-07 20:50  Xs酱~  阅读(505)  评论(0编辑  收藏  举报