zoukankan      html  css  js  c++  java
  • BZOJ2870 最长道路

    题意:给定树,有点权。求一条路径使得最小点权 * 总点数最大。只需输出这个最大值。5w。

    解:树上路径问题,点分治。

    考虑合并两个子树的时候,答案的形式是val1 * (d1 + d2),当1是新插入的节点的时候,只需在val比它大的点中选出一个最大的d2,这树状数组就可以做到。

    当2是新插入的节点时候,好像需要凸包了?但是我们完全不虚啊,因为我们倒序枚举子树就能让2在1之前插入。

    于是正反枚举两次子树,拿树状数组维护一下后缀最大值就行了。

    复杂度O(nlog2n)

      1 /**
      2  * There is no end though there is a start in space. ---Infinity.
      3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
      4  * Only the person who was wisdom can read the most foolish one from the history.
      5  * The fish that lives in the sea doesn't know the world in the land.
      6  * It also ruins and goes if they have wisdom.
      7  * It is funnier that man exceeds the speed of light than fish start living in the land.
      8  * It can be said that this is an final ultimatum from the god to the people who can fight.
      9  *
     10  * Steins;Gate
     11  */
     12 
     13 #include <bits/stdc++.h>
     14 
     15 #define forson(x, i) for(int i = e[x]; i; i = edge[i].nex)
     16 
     17 typedef long long LL;
     18 const int N = 50010, INF = 0x3f3f3f3f;
     19 
     20 struct Edge {
     21     int nex, v;
     22 }edge[N << 1], edge2[N << 1]; int tp, tp2;
     23 
     24 int e[N], n, siz[N], _n, root, small, e2[N], xx, d[N], Val[N];
     25 LL val[N], X[N], ans;
     26 bool del[N];
     27 
     28 inline void add(int x, int y) {
     29     tp++;
     30     edge[tp].v = y;
     31     edge[tp].nex = e[x];
     32     e[x] = tp;
     33     return;
     34 }
     35 
     36 inline void add2(int x, int y) {
     37     tp2++;
     38     edge2[tp2].v = y;
     39     edge2[tp2].nex = e2[x];
     40     e2[x] = tp2;
     41     return;
     42 }
     43 
     44 namespace ta {
     45     int ta[N];
     46     inline void add(int x, int v) {
     47         x = xx + 1 - x;
     48         for(int i = x; i <= xx; i += i & (-i)) {
     49             ta[i] = std::max(ta[i], v);
     50         }
     51         return;
     52     }
     53     inline void del(int x) {
     54         x = xx + 1 - x;
     55         for(int i = x; i <= xx; i += i & (-i)) {
     56             ta[i] = -INF;
     57         }
     58         return;
     59     }
     60     inline int getMax(int x) {
     61         x = xx + 1 - x;
     62         int ans = -INF;
     63         for(int i = x; i; i -= i & (-i)) {
     64             ans = std::max(ans, ta[i]);
     65         }
     66         return ans;
     67     }
     68 }
     69 
     70 void getroot(int x, int f) {
     71     siz[x] = 1;
     72     int large = 0;
     73     forson(x, i) {
     74         int y = edge[i].v;
     75         if(y == f || del[y]) continue;
     76         getroot(y, x);
     77         siz[x] += siz[y];
     78         if(siz[y] > large) {
     79             large = siz[y];
     80         }
     81     }
     82     if(_n - siz[x] > large) {
     83         large = _n - siz[x];
     84     }
     85     if(small > large) {
     86         small = large;
     87         root = x;
     88     }
     89     return;
     90 }
     91 
     92 void DFS_1(int x, int f) {
     93     siz[x] = 1;
     94     d[x] = d[f] + 1;
     95     Val[x] = std::min(Val[f], (int)val[x]);
     96     ans = std::max(ans, X[Val[x]] * (d[x] + ta::getMax(Val[x])));
     97     forson(x, i) {
     98         int y = edge[i].v;
     99         if(del[y] || y == f) continue;
    100         DFS_1(y, x);
    101         siz[x] += siz[y];
    102     }
    103     return;
    104 }
    105 
    106 void DFS_2(int x, int f) {
    107     ta::add(Val[x], d[x] + 1);
    108     forson(x, i) {
    109         int y = edge[i].v;
    110         if(y == f || del[y]) continue;
    111         DFS_2(y, x);
    112     }
    113     return;
    114 }
    115 
    116 void DFS_3(int x, int f) {
    117     ta::del(Val[x]);
    118     forson(x, i) {
    119         int y = edge[i].v;
    120         if(del[y] || y == f) {
    121             continue;
    122         }
    123         DFS_3(y, x);
    124     }
    125     return;
    126 }
    127 
    128 void poi_div(int x) {
    129     small = INF;
    130     getroot(x, 0);
    131     x = root;
    132 
    133     d[x] = 0;
    134     Val[x] = val[x];
    135     ta::add(Val[x], 1);
    136     forson(x, i) {
    137         int y = edge[i].v;
    138         if(del[y]) continue;
    139         DFS_1(y, x);
    140         DFS_2(y, x);
    141     }
    142     DFS_3(x, 0);
    143     // ---------
    144     for(int i = e2[x]; i; i = edge2[i].nex) {
    145         int y = edge2[i].v;
    146         if(del[y]) continue;
    147         DFS_1(y, x);
    148         DFS_2(y, x);
    149     }
    150     ans = std::max(ans, X[val[x]] * ta::getMax(val[x]));
    151     DFS_3(x, 0);
    152 
    153     del[x] = 1;
    154     forson(x, i) {
    155         int y = edge[i].v;
    156         if(del[y]) continue;
    157         _n = siz[y];
    158         poi_div(y);
    159     }
    160     return;
    161 }
    162 
    163 int main() {
    164 
    165     scanf("%d", &n);
    166     for(int i = 1; i <= n; i++) {
    167         scanf("%lld", &val[i]);
    168         X[i] = val[i];
    169     }
    170     std::sort(X + 1, X + n + 1);
    171     xx = std::unique(X + 1, X + n + 1) - X - 1;
    172     for(int i = 1; i <= n; i++) {
    173         val[i] = std::lower_bound(X + 1, X + xx + 1, val[i]) - X;
    174     }
    175     ans = X[xx];
    176     for(int i = 1, x, y; i < n; i++) {
    177         scanf("%d%d", &x, &y);
    178         add(x, y); add(y, x);
    179     }
    180     for(int x = 1; x <= n; x++) {
    181         forson(x, i) {
    182             add2(x, edge[i].v);
    183         }
    184     }
    185 
    186     poi_div(1);
    187 
    188     printf("%lld
    ", ans);
    189     return 0;
    190 }
    AC代码

    题外话:感觉能树形DP,但是要线段树合并 + 凸包合并,虚的一批...

    还发现了一个O(nlogn)的做法,只需多叉转二叉然后O(n) - O(1)lca即可实现,瓶颈在于排序...

    然而这题是边分治模板题...

  • 相关阅读:
    python实现RSA加密解密方法
    信息安全-2:python之hill密码算法[原创]
    信息安全-4:公钥密码体制之背包算法[原创]
    python之import子目录文件
    python之路径导入
    python之局部变量引用赋值前的结果
    python之socket-ssh实例
    python之面向对象与构造函数
    git搜索--grep
    git日志--log
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10706443.html
Copyright © 2011-2022 走看看