ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

雨天的尾巴(线段树合并 & 树上差分综合)

2022-04-09 08:32:40  阅读:166  来源: 互联网

标签:rt int 线段 差分 vol 雨天 lsp rsp sum


  1 #include <bits/stdc++.h>
  2 #define Re register int
  3 #define LL long long
  4 #define ki cout << endl;
  5 
  6 using namespace std;
  7 
  8 //打个雨天的尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾尾巴
  9 //我复习了lca...............学习了差分....
 10 //可真行
 11 /*
 12                             1
 13                         2       3
 14                      4    5    6   7
 15                    8          9
 16 点差分
 17     volume_up
 18     vol[u]++;
 19     vol[v]++;
 20     vol[lca(u, v)] --;
 21     vol[pre[lca(u, v)]] --;
 22     最后求前缀和就是给u - > v路径是都加了个一
 23 eg:   1 2 3 4 5 6(普通差分)
 24     给 2 - > 5 加一
 25     就是 vol[2] + 1  | vol[5] + 1 | vol[6] - 1
 26     求前缀和就是2 -> 5都加一,而五之后没加
 27      给8 -> 5树上每个点都加一(树上差分)
 28     按上边(最上边)操作即可,因为到lca加了两个,而从lca的爹到根都也都多加了2但vol[lca(u, v)]--已经减了一次,所以再减一次就行,而lca留一次,所以只减一个
 29 边差分
 30     vol[u]++;
 31     vol[v]++;
 32     vol[lca(u, v)] -= 2;
 33     边为点到其父亲的边
 34     显而易见lca到跌的边不需要,所以减两个
 35 */
 36 namespace kiritokazuto {
 37     template <typename T> inline void in(T &x) {
 38         int f = 0; x = 0; char c = getchar();
 39         while(c < '0' || c > '9')f |= c == '-', c = getchar();
 40         while(c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
 41         x = f ? -x : x;
 42     }
 43     template <typename T> inline void ot(T x) {
 44         if(x < 0)putchar('-'), x = -x;
 45         if(x > 9)ot(x / 10); putchar(x % 10 | '0');
 46     }
 47 }
 48 /*
 49 所以,综上所述,这个题就成了线段树合并的真真正正的板子题
 50 但是合并时可能
 51 出现vol[rt[x]]不为0
 52 但是sum[rt[x]]为0的情况
 53 即节点编号为vol[rt[x]]的救济粮数量为0(就是他这里可能是别的改了)
 54 所以ans[x] = 0
 55 */
 56 using namespace kiritokazuto;
 57 const int maxn =  6e6 + 10, Inf = 1e5;
 58 int len = 0;
 59 int head[maxn];
 60 int tot;
 61 int n, m;
 62 int ans[maxn];
 63 struct QWMXQ {
 64     int next;
 65     int to;
 66     //int dis;
 67 }a[maxn];
 68 int sum[maxn];
 69 int vol[maxn];
 70 int root[maxn];
 71 struct WMX {
 72     int lson, rson;
 73     #define lsp(x) tr[x].lson
 74     #define rsp(x) tr[x].rson
 75     #define mid ((l + r) >> 1)
 76 }tr[maxn];
 77 //差分直接给每一棵线段树上搞了,所以这里的vol[x]实际上是表示以x为根的子树的答案->从下向上合并的时候
 78 inline void Qian(int from, int to) {
 79     a[++len].to = to;
 80     //a[len].dis = dis;
 81     a[len].next = head[from];
 82     head[from] = len;
 83 }
 84 int f[maxn][20];//老年倍增数组
 85 int deep[maxn];
 86 inline void pushup(int rt) {
 87     if(lsp(rt) == 0) {
 88         sum[rt] = sum[rsp(rt)];
 89         vol[rt] = vol[rsp(rt)];
 90         return;
 91     }
 92     if(rsp(rt) == 0) {
 93         sum[rt] = sum[lsp(rt)];
 94         vol[rt] = vol[lsp(rt)];
 95         return;
 96     }
 97     if(sum[lsp(rt)] >= sum[rsp(rt)]) {
 98         sum[rt] = sum[lsp(rt)];
 99         vol[rt] = vol[lsp(rt)];
100         //return;
101     }else {
102         sum[rt] = sum[rsp(rt)];
103         vol[rt] = vol[rsp(rt)];
104        // return;
105     }
106 }
107 
108 inline void insert(int &rt, int l, int r, int pos, int val) {
109         if(!rt)rt = ++tot;
110         if(l == r) {
111             vol[rt] = pos;//存下该节点编号对应的真正树上的编号->动态开点
112             sum[rt] += val;
113             return;//结束啊!!!
114         } 
115         if(pos <= mid) insert(lsp(rt), l ,mid, pos, val);
116         else insert(rsp(rt), mid + 1, r, pos, val);
117         pushup(rt);
118 }
119 
120 
121 inline int merge(int rr, int tt, int l, int r) {
122     if(!rr)return tt;
123     if(!tt)return rr;
124     if(l == r) {
125         sum[rr] += sum[tt];
126         return rr;//记得返回->叶子
127     }
128     lsp(rr) = merge(lsp(rr), lsp(tt), l, mid);
129     rsp(rr) = merge(rsp(rr), rsp(tt), mid + 1, r);
130     pushup(rr);//记得pushup
131     return rr;
132 }
133 
134 void dfs(int x, int fa) {
135     deep[x] = deep[fa] + 1;
136     f[x][0] = fa;//x 的 2 ^ 0 即 x 向上 翻 1的祖先就是他的爹
137     for(Re i = 1; i <= 20; i ++)  {
138         f[x][i] = f[f[x][i - 1]][i - 1];//x 的 2 ^ i 的爹是x 的 2 ^ j - 1的 2 ^ j - 1;
139     }
140     for(Re i = head[x], to; i ; i = a[i].next) {
141         to = a[i].to;
142         if(to == fa)continue;
143         dfs(to, x);
144     }
145 } 
146 
147 int LCA(int a, int b) {
148     if(deep[a] > deep[b])swap(a, b);//a深,把a换上来
149     for(Re i = 20; i >= 0; i --) {
150         if(deep[a] <= deep[f[b][i]])b = f[b][i];//拉到同一层
151     }
152     if(a == b)return a;
153     for(Re i = 20; i >= 0; i --) {
154         if(f[a][i] != f[b][i]) {
155             a = f[a][i];
156             b = f[b][i];
157         }
158     }    
159     return f[a][0];
160 }
161 
162 inline void work(int x, int fa) {
163     for(Re i = head[x], to; i; i = a[i].next) {
164         to = a[i].to;
165         if(to == fa)continue;
166         work(to, x);
167         root[x] = merge(root[x], root[to], 1, Inf);
168     }
169     ans[x] = vol[root[x]];
170     if(sum[root[x]] == 0)ans[x] = 0;
171 }
172 signed main () {
173 //    freopen("in.txt", "r", stdin);
174 //    freopen("out.txt", "w", stdout);
175     in(n);
176     in(m);
177     for(int i = 1, x ,y; i < n; i ++) {
178         in(x);
179         in(y);
180         Qian(x, y);
181         Qian(y, x);
182     }
183     dfs(1, 0);
184     //cout << "?????????";
185     for(int i = 1, x,  y, z; i <= m; i ++)  {
186         in(x);
187         in(y);
188         in(z);
189         int lca = LCA(x, y);
190         insert(root[x], 1, Inf, z, 1);
191         insert(root[y], 1, Inf, z, 1);
192         insert(root[lca], 1, Inf, z, -1);
193         insert(root[f[lca][0]], 1, Inf, z, -1);
194     }
195     work(1, 0);
196     for(Re i = 1; i <= n; i ++) {
197         cout << ans[i] << endl;
198     }
199     return 0;
200 }

 

标签:rt,int,线段,差分,vol,雨天,lsp,rsp,sum
来源: https://www.cnblogs.com/kiritokazuto/p/16120770.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有