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\n", 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 }

 

你可能感兴趣的:(CodeForces 593D Happy Tree Party)