洛谷P4556 雨天的尾巴

题目链接

题解:

因为一个点可能存放多种物品,直接开二维数组进行统计时间、空间复杂度都不能承受。因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一颗权值线段树来维护多种物品以及其数量,然后最后在回溯时合并,这样就可以得到我们所需要的信息了。

因为题目中要求的是哪一种物品,所以我们可以顺带维护一下位置信息,就不用到时候每次去query了。

注意一下,就是当一个点的sum为0时,其pos应该为置为0。

详见代码吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, m;
struct Edge{
int v, next;
}e[N << 1];
int head[N], tot, D;
void adde(int u, int v) {
e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
}
int f[N][22], deep[N] ;
int rt[N], ls[N * 100], rs[N * 100], pos[N * 100], sum[N * 100] ;
int X[N], Y[N], Z[N], b[N], ans[N];
void dfs1(int u, int fa) {
deep[u] = deep[fa] + 1;
for(int i = head[u]; i != -1; i = e[i].next){
int v = e[i].v;
if(v == fa) continue ;
f[v][0] = u;
for(int j = 1; j <= 20; j++) f[v][j] = f[f[v][j - 1]][j - 1] ;
dfs1(v, u) ;
}
}
int LCA(int x, int y) {
if(deep[x] < deep[y]) swap(x, y);
for(int i = 20; i >= 0; i--) {
if(deep[f[x][i]] >= deep[y]) x = f[x][i] ;
}
if(x == y) return x;
for(int i = 20; i >= 0; i--) {
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i] ;
}
return f[x][0] ;
}
void insert(int o, int l, int r, int val, int sign) {
if(l == r) {
sum[o] += sign;
pos[o] = sum[o] > 0 ? l : 0;
return ;
}
int mid = (l + r) >> 1;
if(val <= mid) {
if(!ls[o]) ls[o] = ++tot;
insert(ls[o], l, mid, val, sign) ;
} else {
if(!rs[o]) rs[o] = ++tot;
insert(rs[o], mid + 1, r, val, sign) ;
}
sum[o] = max(sum[ls[o]], sum[rs[o]]) ;
pos[o] = sum[ls[o]] >= sum[rs[o]] ? pos[ls[o]] : pos[rs[o]];
}
int merge(int x, int y, int l, int r) {
if(!x) return y;
if(!y) return x;
if(l == r) {
sum[x] += sum[y] ;
pos[x] = sum[x] > 0 ? l : 0;
return x;
}
int mid = (l + r) >> 1;
ls[x] = merge(ls[x], ls[y], l, mid) ;
rs[x] = merge(rs[x], rs[y], mid + 1, r) ;
sum[x] = max(sum[ls[x]], sum[rs[x]]) ;
pos[x] = sum[ls[x]] >= sum[rs[x]] ? pos[ls[x]] : pos[rs[x]] ;
return x;
}
void dfs2(int u, int fa) {
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(v == fa) continue ;
dfs2(v, u) ;
rt[u] = merge(rt[u], rt[v], 1, D) ;
}
ans[u] = pos[rt[u]];
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> m;
memset(head, -1, sizeof(head)) ;
for(int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
adde(u, v); adde(v, u);
}
dfs1(1, 0) ;
for(int i = 1; i <= n; i++) rt[i] = i;
tot = n;
for(int i = 1; i <= m; i++) {
cin >> X[i] >> Y[i] >> Z[i] ;
b[i] = Z[i] ;
}
sort(b + 1, b + m + 1);
D = unique(b + 1, b + m + 1) - b - 1;
for(int i = 1; i <= m; i++) {
int x = X[i], y = Y[i], z = Z[i] ;
int k = lower_bound(b + 1, b + D + 1, z) - b;
int lca = LCA(x, y) ;
insert(rt[x], 1, D, k, 1) ;
insert(rt[y], 1, D, k, 1) ;
insert(rt[lca], 1, D, k, -1) ;
if(f[lca][0]) insert(rt[f[lca][0]], 1, D, k, -1) ;
}
dfs2(1, 0) ;
for(int i = 1; i <= n; i++) cout << b[ans[i]] << '\n' ;
return 0;
}

最新文章

  1. Android的计量单位px,in,mm,pt,dp,dip,sp
  2. C#的类型、变量和值
  3. POJ 1250 Tanning Salon
  4. c语言结构体使用方法
  5. 关于Core Location-ios定位
  6. 02、Unicode 汉子转码小工具
  7. 什么是j2ee ??EJB与j2ee的关系?? 请看百度百科
  8. windows搭建代理服务器
  9. 数据库复习总结(20)-存储过程以及.net调用存储过程
  10. &lt;script&gt;标签中的 defer 与 async区别
  11. 【LSGDOJ 1333】任务安排 dp
  12. Linux系统上安装MySQL(rpm)
  13. 解读《德勤2017年全球CIO报告》:顶级CIO的炼成之道
  14. Windows Server 2012配置iis遇到的问题
  15. django项目 报错:ImportError: cannot import name choice
  16. 关于systemctl
  17. sql server 查询某个表被哪些存储过程调用
  18. ionic调用手机系统的拨打电话
  19. window.localStorag使用
  20. websocket学习和群聊实现

热门文章

  1. Log4j之HelloWorld
  2. 简单说说JavaScript的Generator 实现(ES6)
  3. Golang微服务实践
  4. prometheus自定义监控指标——实战
  5. 【视频开发】【计算机视觉】相机标定(Camera calibration)《二》
  6. jQuery必知必会
  7. Docker 下的Zookeeper以及.ne core 的分布式锁
  8. 『一维线性dp的四边形不等式优化』
  9. SocketChannel简述
  10. Firefox 无法播放 youtube