zoukankan      html  css  js  c++  java
  • LOJ#2339 通道

    题意:给你三棵树,求所有点对在三棵树上的距离和中的最大值。

    解:首先有个暴力,然后还有个迭代乱搞,可以得到61分...

     1 namespace bf {
     2     inline void solve() {
     3         for(int i = 1; i <= n; i++) {
     4             for(int j = i; j <= n; j++) {
     5                 Ans = std::max(Ans, t1.dis(i, j) + t2.dis(i, j) + t3.dis(i, j));
     6             }
     7         }
     8         printf("%lld
    ", Ans);
     9         return;
    10     }
    11 }
    12 
    13 namespace naive {
    14     inline void Rand() {
    15         int x = rand() % n + 1;
    16         for(int T = 1; T <= 10; T++) {
    17             int y = 0;
    18             LL large = -INF;
    19             for(int i = 1; i <= n; i++) {
    20                 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i);
    21                 if(temp > large) {
    22                     large = temp;
    23                     y = i;
    24                 }
    25             }
    26             x = y;
    27             Ans = std::max(Ans, large);
    28         }
    29         return;
    30     }
    31     inline void solve() {
    32         for(int i = 1; i <= 10; i++) {
    33             Rand();
    34         }
    35         printf("%lld
    ", Ans);
    36         return;
    37     }
    38 }
    61分代码

    有个部分分是只有两棵树。

    我们在第一棵树上枚举lca,那么就相当于把这些点全部挂到第二棵树上,边权是深度。此时可以用直径的性质来维护最远点对。 

     1 #define forson(t, x, i) for(int i = t.e[x], y = t.edge[i].v; i; i = t.edge[i].nex, y = t.edge[i].v)
     2 
     3 inline bool check_same() {
     4     std::vector<uLL> v, u;
     5     for(int x = 1; x <= n; x++) {
     6         v.clear(), u.clear();
     7         forson(t2, x, i) {
     8             v.push_back(t2.edge[i].len * N + y);
     9         }
    10         forson(t3, x, i) {
    11             u.push_back(t3.edge[i].len * N + y);
    12         }
    13         int len = v.size();
    14         if(len != u.size()) return false;
    15         std::sort(v.begin(), v.end());
    16         std::sort(u.begin(), u.end());
    17         for(int i = 0; i < len; i++) {
    18             if(v[i] != u[i]) return false;
    19         }
    20     }
    21     return true;
    22 }
    23 
    24 namespace same {
    25     Data data[N];
    26     inline LL exdis(const int &x, const int &y) {
    27         return 2 * t2.dis(x, y) + t1.d[x] + t1.d[y];
    28     }
    29     inline void merge(Data &x, const Data &y, const LL &v) {
    30         int xa = x.a, xb = x.b, ya = y.a, yb = y.b;
    31         LL d12 = exdis(xa, xb), d34 = exdis(ya, yb);
    32         LL d13 = exdis(xa, ya), d14 = exdis(xa, yb);
    33         LL d23 = exdis(xb, ya), d24 = exdis(xb, yb);
    34         if(d34 > d12) {
    35             d12 = d34;
    36             x = y;
    37         }
    38         if(d13 > d12) {
    39             d12 = d13;
    40             x.a = xa;
    41             x.b = ya;
    42         }
    43         if(d14 > d12) {
    44             d12 = d14;
    45             x.a = xa;
    46             x.b = yb;
    47         }
    48         if(d23 > d12) {
    49             d12 = d23;
    50             x.a = xb;
    51             x.b = ya;
    52         }
    53         if(d24 > d12) {
    54             d12 = d24;
    55             x.a = xb;
    56             x.b = yb;
    57         }
    58         Ans = std::max(Ans, std::max(std::max(d13, d14), std::max(d23, d24)) - v);
    59         return;
    60     }
    61     void DFS(int x, int f) {
    62         data[x] = Data(x, x);
    63         forson(t1, x, i) {
    64             if(y == f) continue;
    65             DFS(y, x);
    66             merge(data[x], data[y], t1.d[x] << 1);
    67         }
    68         return;
    69     }
    70     inline void solve() {
    71         DFS(1, 0);
    72         return;
    73     }
    74 }
    46分代码

    正解:这不还有一棵树吗?根据暴力写挂和情报中心的经验,我们边分治 + 虚树,即可去掉第一棵树的限制。把边分治的两部分染成不同颜色。

    在第二棵树上建虚树,第三棵树上维护两种颜色的直径。

    答案就用不同颜色不同集合的来更新。合并的时候每种颜色分开合并。 

      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 typedef long long LL;
     16 typedef unsigned long long uLL;
     17 const int N = 200010;
     18 const LL INF = 4e18;
     19 
     20 struct Edge {
     21     int nex, v;
     22     LL len;
     23     bool vis;
     24 }edge[N << 1], EDGE[N << 1]; int tp = 1, TP;
     25 
     26 struct Data {
     27     int a, b;
     28     LL v;
     29     Data(int A = 0, int B = 0, LL V = 0) {
     30         a = A;
     31         b = B;
     32         v = V;
     33     }
     34 }data1[N], data2[N];
     35 
     36 int pw[N << 1], n, rdP[N], e[N], siz[N], Cnt, _n, small, root, use[N], Time, vis[N], E[N], K, imp[N], RT, col[N];
     37 LL Ans, d[N];
     38 
     39 struct Tree {
     40     Edge edge[N << 1]; int tp = 1;
     41     int e[N], pos2[N], num2, ST[N << 1][20], deep[N];
     42     LL d[N];
     43     inline void add(int x, int y, LL z) {
     44         edge[++tp].v = y;
     45         edge[tp].len = z;
     46         edge[tp].nex = e[x];
     47         e[x] = tp;
     48         return;
     49     }
     50     void DFS_1(int x, int f) {
     51         pos2[x] = ++num2;
     52         ST[num2][0] = x;
     53         deep[x] = deep[f] + 1;
     54         for(int i = e[x]; i; i = edge[i].nex) {
     55             int y = edge[i].v;
     56             if(y == f) continue;
     57             d[y] = d[x] + edge[i].len;
     58             DFS_1(y, x);
     59             ST[++num2][0] = x;
     60         }
     61         return;
     62     }
     63     inline void prework() {
     64         for(int j = 1; j <= pw[num2]; j++) {
     65             for(int i = 1; i + (1 << j) - 1 <= num2; i++) {
     66                 if(deep[ST[i][j - 1]] < deep[ST[i + (1 << (j - 1))][j - 1]]) {
     67                     ST[i][j] = ST[i][j - 1];
     68                 }
     69                 else {
     70                     ST[i][j] = ST[i + (1 << (j - 1))][j - 1];
     71                 }
     72             }
     73         }
     74         return;
     75     }
     76     inline int lca(int x, int y) {
     77         x = pos2[x];
     78         y = pos2[y];
     79         if(x > y) std::swap(x, y);
     80         int t = pw[y - x + 1];
     81         if(deep[ST[x][t]] < deep[ST[y - (1 << t) + 1][t]]) {
     82             return ST[x][t];
     83         }
     84         else {
     85             return ST[y - (1 << t) + 1][t];
     86         }
     87     }
     88     inline LL dis(int x, int y) {
     89         if(!x || !y) {
     90             return -INF;
     91         }
     92         return d[x] + d[y] - (d[lca(x, y)] << 1);
     93     }
     94     inline void work() {
     95         LL z;
     96         for(int i = 1, x, y; i < n; i++) {
     97             scanf("%d%d%lld", &x, &y, &z);
     98             add(x, y, z);
     99             add(y, x, z);
    100         }
    101         DFS_1(1, 0);
    102         prework();
    103         return;
    104     }
    105 #undef add
    106 }t1, t2, t3;
    107 
    108 namespace bf {
    109     inline void solve() {
    110         for(int i = 1; i <= n; i++) {
    111             for(int j = i; j <= n; j++) {
    112                 Ans = std::max(Ans, t1.dis(i, j) + t2.dis(i, j) + t3.dis(i, j));
    113             }
    114         }
    115         return;
    116     }
    117 }
    118 
    119 namespace naive {
    120     inline void Rand() {
    121         int x = rand() % n + 1;
    122         for(int T = 1; T <= 5; T++) {
    123             int y = 0;
    124             LL large = -INF;
    125             for(int a = 1; a <= n; a++) {
    126                 int i = rdP[a];
    127                 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i);
    128                 if(temp > large) {
    129                     large = temp;
    130                     y = i;
    131                 }
    132             }
    133             x = y;
    134             Ans = std::max(Ans, large);
    135         }
    136         return;
    137     }
    138     inline void solve() {
    139         for(int i = 1; i <= 5; i++) {
    140             Rand();
    141         }
    142         return;
    143     }
    144 }
    145 
    146 namespace fire {
    147     inline void Rand() {
    148         int x = rand() % n + 1;
    149         for(int T = 1; T <= 5; T++) {
    150             int y = 0;
    151             LL large = -INF;
    152             for(int a = 1; a <= n; a++) {
    153                 int i = rdP[a];
    154                 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i);
    155                 if(temp > large) {
    156                     large = temp;
    157                     y = i;
    158                 }
    159                 else if(rand() % 100 < T) {
    160                     large = temp;
    161                     y = i;
    162                 }
    163             }
    164             x = y;
    165             Ans = std::max(Ans, large);
    166         }
    167         return;
    168     }
    169     inline void solve() {
    170         for(int i = 1; i <= 5; i++) {
    171             Rand();
    172         }
    173         return;
    174     }
    175 }
    176 
    177 #define forson(t, x, i) for(int i = t.e[x], y = t.edge[i].v; i; i = t.edge[i].nex, y = t.edge[i].v)
    178 
    179 inline bool check_same() {
    180     std::vector<uLL> v, u;
    181     for(int x = 1; x <= n; x++) {
    182         v.clear(), u.clear();
    183         forson(t2, x, i) {
    184             v.push_back(t2.edge[i].len * N + y);
    185         }
    186         forson(t3, x, i) {
    187             u.push_back(t3.edge[i].len * N + y);
    188         }
    189         int len = v.size();
    190         if(len != u.size()) return false;
    191         std::sort(v.begin(), v.end());
    192         std::sort(u.begin(), u.end());
    193         for(int i = 0; i < len; i++) {
    194             if(v[i] != u[i]) return false;
    195         }
    196     }
    197     return true;
    198 }
    199 
    200 namespace same {
    201     Data data[N];
    202     inline LL exdis(const int &x, const int &y) {
    203         return 2 * t2.dis(x, y) + t1.d[x] + t1.d[y];
    204     }
    205     inline void merge(Data &x, const Data &y, const LL &v) {
    206         int xa = x.a, xb = x.b, ya = y.a, yb = y.b;
    207         LL d12 = exdis(xa, xb), d34 = exdis(ya, yb);
    208         LL d13 = exdis(xa, ya), d14 = exdis(xa, yb);
    209         LL d23 = exdis(xb, ya), d24 = exdis(xb, yb);
    210         if(d34 > d12) {
    211             d12 = d34;
    212             x = y;
    213         }
    214         if(d13 > d12) {
    215             d12 = d13;
    216             x.a = xa;
    217             x.b = ya;
    218         }
    219         if(d14 > d12) {
    220             d12 = d14;
    221             x.a = xa;
    222             x.b = yb;
    223         }
    224         if(d23 > d12) {
    225             d12 = d23;
    226             x.a = xb;
    227             x.b = ya;
    228         }
    229         if(d24 > d12) {
    230             d12 = d24;
    231             x.a = xb;
    232             x.b = yb;
    233         }
    234         Ans = std::max(Ans, std::max(std::max(d13, d14), std::max(d23, d24)) - v);
    235         return;
    236     }
    237     void DFS(int x, int f) {
    238         data[x] = Data(x, x);
    239         forson(t1, x, i) {
    240             if(y == f) continue;
    241             DFS(y, x);
    242             merge(data[x], data[y], t1.d[x] << 1);
    243         }
    244         return;
    245     }
    246     inline void solve() {
    247         DFS(1, 0);
    248         return;
    249     }
    250 }
    251 
    252 #undef forson
    253 
    254 inline void add(int x, int y, LL z) {
    255     edge[++tp].v = y;
    256     edge[tp].len = z;
    257     edge[tp].nex = e[x];
    258     e[x] = tp;
    259     return;
    260 }
    261 
    262 inline void ADD(int x, int y) {
    263     EDGE[++TP].v = y;
    264     EDGE[TP].nex = E[x];
    265     E[x] = TP;
    266     return;
    267 }
    268 
    269 void rebuild(int x, int f) {
    270     int temp = 0;
    271     for(int i = t1.e[x]; i; i = t1.edge[i].nex) {
    272         int y = t1.edge[i].v;
    273         LL len = t1.edge[i].len;
    274         if(y == f) continue;
    275         if(!temp) {
    276             add(x, y, len);
    277             add(y, x, len);
    278             temp = x;
    279         }
    280         else if(!t1.edge[i].nex) {
    281             add(temp, y, len);
    282             add(y, temp, len);
    283         }
    284         else {
    285             add(temp, ++Cnt, 0);
    286             add(Cnt, temp, 0);
    287             temp = Cnt;
    288             add(temp, y, len);
    289             add(y, temp, len);
    290         }
    291         rebuild(y, x);
    292     }
    293     return;
    294 }
    295 
    296 void getroot(int x, int f) {
    297     siz[x] = 1;
    298     for(int i = e[x]; i; i = edge[i].nex) {
    299         int y = edge[i].v;
    300         if(y == f || edge[i].vis) continue;
    301         getroot(y, x);
    302         siz[x] += siz[y];
    303         if(std::max(siz[y], _n - siz[y]) < small) {
    304             small = std::max(siz[y], _n - siz[y]);
    305             root = i;
    306         }
    307     }
    308     return;
    309 }
    310 
    311 inline void work(int x) {
    312     if(use[x] == Time) return;
    313     use[x] = Time;
    314     E[x] = col[x] = 0;
    315     return;
    316 }
    317 
    318 void DFS_1(int x, int f, int flag) {
    319     siz[x] = 1;
    320     if(x <= n) {
    321         work(x);
    322         imp[++K] = x;
    323         col[x] = flag;
    324     }
    325     for(int i = e[x]; i; i = edge[i].nex) {
    326         int y = edge[i].v;
    327         if(y == f || edge[i].vis) continue;
    328         d[y] = d[x] + edge[i].len;
    329         DFS_1(y, x, flag);
    330         siz[x] += siz[y];
    331     }
    332     return;
    333 }
    334 
    335 inline bool cmp(const int &a, const int &b) {
    336     return t2.pos2[a] < t2.pos2[b];
    337 }
    338 
    339 inline void build_t() {
    340     static int stk[N], top;
    341     std::sort(imp + 1, imp + K + 1, cmp);
    342     K = std::unique(imp + 1, imp + K + 1) - imp - 1;
    343     stk[top = 1] = imp[1];
    344     for(int i = 2; i <= K; i++) {
    345         int x = imp[i], y = t2.lca(x, stk[top]);
    346         work(y);
    347         while(top > 1 && t2.pos2[y] <= t2.pos2[stk[top - 1]]) {
    348             ADD(stk[top - 1], stk[top]);
    349             top--;
    350         }
    351         if(stk[top] != y) {
    352             ADD(y, stk[top]);
    353             stk[top] = y;
    354         }
    355         stk[++top] = x;
    356     }
    357     while(top > 1) {
    358         ADD(stk[top - 1], stk[top]);
    359         top--;
    360     }
    361     RT = stk[top];
    362     return;
    363 }
    364 
    365 inline bool operator < (const Data &a, const Data &b) {
    366     return a.v < b.v;
    367 }
    368 
    369 inline LL exdis(int x, int y) {
    370     return t3.dis(x, y) + d[x] + d[y] + t2.d[x] + t2.d[y];
    371 }
    372 
    373 inline void merge(Data &x, const Data &y) {
    374     int xa = x.a, xb = x.b, ya = y.a, yb = y.b;
    375     LL d12 = exdis(xa, xb), d34 = exdis(ya, yb);
    376     LL d13 = exdis(xa, ya), d14 = exdis(xa, yb);
    377     LL d23 = exdis(xb, ya), d24 = exdis(xb, yb);
    378     if(d34 > d12) {
    379         d12 = d34;
    380         x = y;
    381     }
    382     if(d13 > d12) {
    383         d12 = d13;
    384         x.a = xa;
    385         x.b = ya;
    386     }
    387     if(d14 > d12) {
    388         d12 = d14;
    389         x.a = xa;
    390         x.b = yb;
    391     }
    392     if(d23 > d12) {
    393         d12 = d23;
    394         x.a = xb;
    395         x.b = ya;
    396     }
    397     if(d24 > d12) {
    398         x.a = xb;
    399         x.b = yb;
    400     }
    401     return;
    402 }
    403 
    404 inline void merge(int x, int y, LL v) {
    405     int p1 = data1[x].a, p2 = data1[x].b, p3 = data2[x].a, p4 = data2[x].b;
    406     int p5 = data1[y].a, p6 = data1[y].b, p7 = data2[y].a, p8 = data2[y].b;
    407     /// cal ans
    408     Ans = std::max(Ans, std::max(std::max(exdis(p1, p7), exdis(p1, p8)), std::max(exdis(p2, p7), exdis(p2, p8))) + v);
    409     Ans = std::max(Ans, std::max(std::max(exdis(p3, p5), exdis(p3, p6)), std::max(exdis(p4, p5), exdis(p4, p6))) + v);
    410     /// update data1[x] data2[x]
    411     merge(data1[x], data1[y]);
    412     merge(data2[x], data2[y]);
    413     return;
    414 }
    415 
    416 void DFS_2(int x, LL v) {
    417     data1[x] = data2[x] = Data(0, 0);
    418     if(col[x] == 1) {
    419         data1[x] = Data(x, x);
    420     }
    421     else if(col[x] == 2) {
    422         data2[x] = Data(x, x);
    423     }
    424     for(int i = E[x]; i; i = EDGE[i].nex) {
    425         int y = EDGE[i].v;
    426         DFS_2(y, v);
    427         merge(x, y, v - (t2.d[x] << 1));
    428     }
    429     return;
    430 }
    431 
    432 void e_div(int x) {
    433     if(_n == 1) {
    434         return;
    435     }
    436     small = N;
    437     getroot(x, 0);
    438     edge[root].vis = edge[root ^ 1].vis = 1;
    439     x = edge[root].v;
    440     int y = edge[root ^ 1].v;
    441 
    442     ++Time;
    443     d[x] = d[y] = K = TP = 0;
    444     DFS_1(x, 0, 1);
    445     DFS_1(y, 0, 2);
    446     build_t();
    447     DFS_2(RT, edge[root].len);
    448 
    449     ///
    450     _n = siz[x];
    451     e_div(x);
    452     _n = siz[y];
    453     e_div(y);
    454     return;
    455 }
    456 
    457 int main() {
    458 
    459     srand(15);
    460     scanf("%d", &n);
    461     for(int i = 2; i <= 2 * n; i++) {
    462         pw[i] = pw[i >> 1] + 1;
    463     }
    464     for(int i = 1; i <= n; i++) {
    465         rdP[i] = i;
    466     }
    467     std::random_shuffle(rdP + 1, rdP + n + 1);
    468     t1.work();
    469     t2.work();
    470     t3.work();
    471     /*if(n <= 3000) {
    472         bf::solve();
    473         printf("%lld
    ", Ans);
    474         return 0;
    475     }
    476     if(check_same()) {
    477         same::solve();
    478         printf("%lld
    ", Ans);
    479         return 0;
    480     }
    481     naive::solve();
    482     fire::solve();*/
    483     /// ---------------------------
    484     Cnt = n;
    485     rebuild(1, 0);
    486     _n = Cnt;
    487     e_div(1);
    488     printf("%lld
    ", Ans);
    489     return 0;
    490 }
    AC代码

    其实也不是很长......大概只有hope的一半多一点。虽然我没写hope......

  • 相关阅读:
    FreeRTOS之源码 及 移植详解
    FreeRTOS之Tracealyzer for FreeRTOS(FreeRTOS+Trace) 详解(源码解析+移植)
    FreeRTOS之全配置项详解、裁剪(FreeRTOSConfig.h)
    linux下安装oracle中遇到的一些问题
    RedHat Enterprise Linux 6 配置Xmanager ,实现图形界面连接
    Linux ext2/ext3文件系统详解
    对固态硬盘ssd进行4k对齐
    在CentOs6.5安装jdk
    Android的API版本和名称对应关系
    Java反射机制及Method.invoke详解
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10718003.html
Copyright © 2011-2022 走看看