ICode9

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

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

2022-07-24 15:02:01  阅读:156  来源: 互联网

标签:lc int P4556 线段 合并 pos tr dat rc


显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案。

用动态开点的方式建立线段树,注意离散化。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N = 1e5 + 10;
  4 struct node {
  5     int lc, rc, dat, pos;//dat记录最多的物品的次数,pos记录位置 
  6 }tr[N * 20 * 4];
  7 int head[N], to[N << 1], nxt[N << 1], tot;
  8 int n, m, num, cnt, t, ans[N];
  9 int d[N], st[N][20], rt[N], X[N], Y[N], Z[N], val[N];
 10 inline int read() {
 11     int x = 0,f = 1;char ch = getchar();
 12     while (ch<'0' || ch>'9') { if(ch == '-') f = -1;ch = getchar(); }
 13     while (ch >= '0'&&ch <= '9') x = x * 10 + ch - '0',ch = getchar();
 14     return x * f;
 15 }
 16 void add(int x, int y) {
 17     nxt[++tot] = head[x];
 18     head[x] = tot;
 19     to[tot] = y;
 20 }
 21 
 22 void dfs(int u, int f) {
 23      for (int i = head[u]; i; i = nxt[i]) {
 24          int v = to[i];
 25          if (d[v]) continue;
 26          d[v] = d[u] + 1;
 27          st[v][0] = u;
 28          for (int j = 1; j <= t; j++)
 29              st[v][j] = st[st[v][j-1]][j-1];
 30          dfs(v, u);
 31      }
 32 }
 33 
 34 int lca(int x, int y) {
 35     if (d[x] > d[y]) swap(x, y);
 36     for (int i = t; i >= 0; i--) 
 37         if (d[st[y][i]] >= d[x]) y = st[y][i];
 38     if (x == y) return x;
 39     for (int i = t; i >= 0; i--)
 40         if (st[x][i] != st[y][i]) x = st[x][i], y = st[y][i];
 41     return st[x][0]; 
 42 }
 43 
 44 void insert(int p, int l, int r, int val, int k) {
 45     if (l == r) {
 46         tr[p].dat += k;
 47         tr[p].pos = tr[p].dat ? l : 0;
 48         return ;
 49     }
 50     int mid = (l + r) >> 1;
 51     if(val <= mid) {
 52         if (!tr[p].lc)    tr[p].lc = ++num;//动态开点 
 53         insert(tr[p].lc, l, mid, val, k);
 54     }
 55     else {
 56         if (!tr[p].rc) tr[p].rc = ++num;
 57         insert(tr[p].rc, mid + 1, r, val, k);
 58     }
 59     tr[p].dat = max(tr[tr[p].lc].dat, tr[tr[p].rc].dat);
 60     tr[p].pos = tr[tr[p].lc].dat >= tr[tr[p].rc].dat ? tr[tr[p].lc].pos : tr[tr[p].rc].pos;
 61 }
 62 
 63 int merge(int p, int q, int l, int r) {//线段树合并 
 64     if (!p || !q) return p + q;
 65     if (l == r) {
 66         tr[p].dat += tr[q].dat;
 67         tr[p].pos = tr[p].dat ? l : 0;
 68         return p;
 69     }
 70     int mid = (l + r) >> 1;
 71     tr[p].lc = merge(tr[p].lc, tr[q].lc, l, mid);
 72     tr[p].rc = merge(tr[p].rc, tr[q].rc, mid + 1, r);
 73     tr[p].dat = max(tr[tr[p].lc].dat, tr[tr[p].rc].dat);
 74     tr[p].pos = tr[tr[p].lc].dat >= tr[tr[p].rc].dat ? tr[tr[p].lc].pos : tr[tr[p].rc].pos;
 75     return p;
 76 }
 77 
 78 void solve(int x) {
 79     for (int i = head[x]; i; i = nxt[i]) {
 80         int y = to[i];
 81         if (d[y] <= d[x]) continue;
 82         solve(y);
 83         rt[x] = merge(rt[x], rt[y], 1, cnt);
 84     }
 85     ans[x] = tr[rt[x]].pos;
 86 }
 87 
 88 int main() {
 89     n = read(); m = read();
 90     t = log2(n) + 1;
 91     for (int i = 1; i < n; i++) {
 92         int x = read(), y = read();
 93         add(x, y), add(y, x);
 94     }
 95     d[1] = 1, dfs(1,0);
 96     for (int i = 1; i <= n; i++) rt[i] = ++num;
 97     for (int i = 1; i <= m; i++) {
 98         X[i] = read(); Y[i] = read(); Z[i] = read();
 99         val[i] = Z[i];
100     }
101     sort(val + 1, val + m + 1);//离散化 
102     cnt = unique(val + 1, val + m + 1) - val - 1;
103     for (int i = 1; i <= m; i++) {
104         int x = X[i], y = Y[i];
105         int z = lower_bound(val + 1, val + cnt + 1, Z[i]) - val;
106         int p = lca(x, y);
107         //树上差分 
108         insert(rt[x], 1, cnt, z, 1);
109         insert(rt[y], 1, cnt, z, 1);
110         insert(rt[p], 1, cnt, z, -1);
111         if (st[p][0]) insert(rt[st[p][0]], 1, cnt, z, -1);
112     }
113     solve(1);
114     for (int i = 1; i <= n; i++) printf("%d\n", val[ans[i]]);
115     return 0;
116 }

 

标签:lc,int,P4556,线段,合并,pos,tr,dat,rc
来源: https://www.cnblogs.com/yhxnoerror/p/16514516.html

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

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

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

ICode9版权所有