• CodeForces 593D Happy Tree Party


    题目链接: http://codeforces.com/problemset/problem/593/D

    ---------------------------------------------------------------------------------------------------------------

    刚看完题目感觉必须用树链剖分之类的方法,就放弃了,然而我们要发现题目具有如下性质:

    一个$ long long $以内的数如果被大于$1$的数除 几十次就可以除到$0$了

    所以就可以考虑下$LCA$

    但如果长度为$1$的边过多 复杂度又不靠谱了 这时我们又会观察到修改时边的长度只减不增

    因此对于长度为$1$的边 我们可以进行路径压缩

    不过这里的压缩并不是改变原来的树的结构 因为改变树的结构就会麻烦许多

    我们只需把以长度为$1$的边相连的点放在一个集合内, 如果集合内的一个点需要向上查找

    就直接找到这个集合的顶端

    $($尽管集合顶端的点并不一定是两点的$LCA $但由于集合内的边长均为$1$ 实际结果是等价的$)$

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 const int N = 2e5 + 10;
     7 int firste[N], nexte[N << 1], v[N << 1];
     8 long long w[N << 1];
     9 int fa[N], d[N], aim[N], fa2[N];
    10 long long dist[N];
    11 int n, m, e = 1;
    12 void build_edge(int x, int y, long long z)
    13 {
    14     nexte[++e] = firste[x];
    15     firste[x] = e;
    16     v[e] = y;
    17     w[e] = z;
    18 }
    19 int findf(int x)
    20 {
    21     if(fa2[x] == x)
    22         return x;
    23     return fa2[x] = findf(fa2[x]);
    24 }
    25 void dfs(int u)
    26 {
    27     for(int p = firste[u]; p; p = nexte[p])
    28         if(!fa[v[p]])
    29         {
    30             aim[p / 2] = v[p];
    31             fa[v[p]] = u;
    32             d[v[p]] = d[u] + 1;
    33             dist[v[p]] = w[p];
    34             if(w[p] == 1)
    35                 fa2[v[p]] = findf(u);
    36             dfs(v[p]);
    37         }
    38 }
    39 long long check(int x, int y, long long z)
    40 {
    41     while(x != y)
    42     {
    43         if(d[x] < d[y])
    44             swap(x, y);
    45         if(dist[x] == 1)
    46             x = findf(x);
    47         else
    48         {
    49             z /= dist[x];
    50             x = fa[x];
    51             if(!z)
    52                 return z;
    53         }
    54     }
    55     return z;
    56 }
    57 int main()
    58 {
    59     scanf("%d%d", &n, &m);
    60     int x, y;
    61     long long z;
    62     for(int i = 1; i < n; ++i)
    63     {
    64         scanf("%d%d%lld", &x, &y, &z);
    65         build_edge(x, y, z);
    66         build_edge(y, x, z);
    67     }
    68     fa[1] = 1;
    69     dist[1] = 1;
    70     for(int i = 1; i <= n; ++i)
    71         fa2[i] = i;
    72     dfs(1);
    73     while(m--)
    74     {
    75         scanf("%d", &x);
    76         if(x & 1)
    77         {
    78             scanf("%d%d%lld", &x, &y, &z);
    79             printf("%lld
    ", check(x, y, z));
    80         }
    81         else
    82         {
    83             scanf("%d%lld", &x, &z);
    84             int u = aim[x];
    85             dist[u] = z;
    86             if(z == 1)
    87                 fa2[u] = findf(fa[u]);
    88         }
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    26个精选的JavaScript面试问题
    用js实现随机选取10–100之间的10个数字,存入一个数组,并排序
    小程序布局中class='container'的bug
    PHP接收数据数据包的几个方式
    LINUX命令
    VMware的下载安装
    php中Sessions
    php中Cookies
    php文件上传
    php文件处理
  • 原文地址:https://www.cnblogs.com/sagitta/p/5164651.html
Copyright © 2020-2023  润新知