Luogu4556 雨天的尾巴 树上差分线段树合并
Posted itst
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu4556 雨天的尾巴 树上差分线段树合并相关的知识,希望对你有一定的参考价值。
一个套路题……
树上差分+线段树合并即可
注意一个细节:$pushup$的时候如果最大值为$0$一定要把最大值对应的答案也设为$0$,否则会$WA$第二个点
另外如果这道题空限变小了请不要交这份代码,因为这份代码没有卡空间。。。
1 #include<bits/stdc++.h>
2 #define mid ((l + r) >> 1)
3 //This code is written by Itst
4 using namespace std;
5
6 inline int read(){
7 int a = 0;
8 bool f = 0;
9 char c = getchar();
10 while(c != EOF && !isdigit(c)){
11 if(c == ‘-‘)
12 f = 1;
13 c = getchar();
14 }
15 while(c != EOF && isdigit(c)){
16 a = (a << 3) + (a << 1) + (c ^ ‘0‘);
17 c = getchar();
18 }
19 return f ? -a : a;
20 }
21
22 const int MAXN = 100000;
23 struct node{
24 int l , r , maxN , maxInd;
25 }Tree[MAXN * 80];
26 struct Edge{
27 int end , upEd;
28 }Ed[MAXN + 10 << 1];
29 int root[MAXN + 10] , head[MAXN + 10] , jump[MAXN + 10][21] , dep[MAXN + 10] , ans[MAXN + 10] , cntNode , cntEd , N , M;
30
31 inline void addEd(int a , int b){
32 Ed[++cntEd].end = b;
33 Ed[cntEd].upEd = head[a];
34 head[a] = cntEd;
35 }
36
37 void dfs(int now , int fa){
38 jump[now][0] = fa;
39 dep[now] = dep[fa] + 1;
40 for(int i = 1 ; jump[now][i - 1] ; ++i)
41 jump[now][i] = jump[jump[now][i - 1]][i - 1];
42 for(int i = head[now] ; i ; i = Ed[i].upEd)
43 if(Ed[i].end != fa)
44 dfs(Ed[i].end , now);
45 }
46
47 inline int LCA(int x , int y){
48 if(dep[x] < dep[y])
49 swap(x , y);
50 for(int i = 19 ; i >= 0 ; --i)
51 if(dep[x] - (1 << i) >= dep[y])
52 x = jump[x][i];
53 if(x == y)
54 return x;
55 for(int i = 19 ; i >= 0 ; --i)
56 if(jump[x][i] != jump[y][i]){
57 x = jump[x][i];
58 y = jump[y][i];
59 }
60 return jump[x][0];
61 }
62
63 inline void pushup(int now){
64 if(Tree[Tree[now].l].maxN >= Tree[Tree[now].r].maxN){
65 Tree[now].maxN = Tree[Tree[now].l].maxN;
66 Tree[now].maxInd = Tree[Tree[now].l].maxInd;
67 }
68 else{
69 Tree[now].maxN = Tree[Tree[now].r].maxN;
70 Tree[now].maxInd = Tree[Tree[now].r].maxInd;
71 }
72 if(!Tree[now].maxN)
73 Tree[now].maxInd = 0;
74 }
75
76 void insert(int& now , int l , int r , int tar , int num){
77 if(!now)
78 now = ++cntNode;
79 if(l == r){
80 Tree[now].maxN += num;
81 Tree[now].maxInd = tar;
82 return;
83 }
84 if(mid >= tar)
85 insert(Tree[now].l , l , mid , tar , num);
86 else
87 insert(Tree[now].r , mid + 1 , r , tar , num);
88 pushup(now);
89 }
90
91 int merge(int p , int q , int l , int r){
92 if(!p)
93 return q;
94 if(!q)
95 return p;
96 if(l == r){
97 Tree[p].maxN += Tree[q].maxN;
98 return p;
99 }
100 Tree[p].l = merge(Tree[p].l , Tree[q].l , l , mid);
101 Tree[p].r = merge(Tree[p].r , Tree[q].r , mid + 1 , r);
102 pushup(p);
103 return p;
104 }
105
106 void getAns(int now){
107 for(int i = head[now] ; i ; i = Ed[i].upEd)
108 if(Ed[i].end != jump[now][0]){
109 getAns(Ed[i].end);
110 root[now] = merge(root[now] , root[Ed[i].end] , 1 , MAXN);
111 }
112 ans[now] = Tree[root[now]].maxInd;
113 }
114
115 int main(){
116 #ifndef ONLINE_JUDGE
117 freopen("4556.in" , "r" , stdin);
118 //freopen("4556.out" , "w" , stdout);
119 #endif
120 N = read();
121 M = read();
122 for(int i = 1 ; i < N ; ++i){
123 int a = read() , b = read();
124 addEd(a , b);
125 addEd(b , a);
126 }
127 dfs(1 , 0);
128 for(int i = 1 ; i <= M ; ++i){
129 int a = read() , b = read() , c = read() , t = LCA(a , b);
130 insert(root[a] , 1 , MAXN , c , 1);
131 insert(root[b] , 1 , MAXN , c , 1);
132 insert(root[t] , 1 , MAXN , c , -1);
133 insert(root[jump[t][0]] , 1 , MAXN , c , -1);
134 }
135 getAns(1);
136 for(int i = 1 ; i <= N ; ++i)
137 printf("%d
" , ans[i]);
138 return 0;
139 }
以上是关于Luogu4556 雨天的尾巴 树上差分线段树合并的主要内容,如果未能解决你的问题,请参考以下文章
P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)
P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)