zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    186     return 0;
    187 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    用python2和python3伪装浏览器爬取网页
    详解python2 和 python3的区别[附实例]
    两种判断(抓取)网页编码的方法【python版】
    python用两种方法实现url短连接
    2013年1月编程语言排行榜榜单: ObjectiveC继续增长
    年初给力!教你自己动手做手机APP应用!!
    [原创]用python求第1000个质数的值
    linux下如何安装配置redis及主从配置
    第四次博客作业结对项目
    2sat的一些总结
  • 原文地址:https://www.cnblogs.com/rausen/p/4149834.html
Copyright © 2011-2022 走看看