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有约会]雨天的尾巴 (线段树合并 + 树上差分)

P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)

luogu4556 雨天的尾巴 (线段树合并+差分)

[luogu4556]雨天的尾巴

P4556 雨天的尾巴 线段树合并