1. 程式人生 > >Luogu4556 雨天的尾巴 樹上差分、線段樹合並

Luogu4556 雨天的尾巴 樹上差分、線段樹合並

his wap 線段樹合並 struct node ace ans swap ont

傳送門


一個套路題……

樹上差分+線段樹合並即可

註意一個細節:$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\n" , ans[i]); 138 return 0; 139 }

Luogu4556 雨天的尾巴 樹上差分、線段樹合並