BZOJ3307雨天的尾巴——线段树合并
题目描述
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。
输入
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题
输出
输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0
样例输入
8 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50
样例输出
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50
1<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int h[100010];
int root[100010];
int ls[6000010];
int rs[6000010];
int next[200010];
int head[100010];
int to[200010];
int f[100010][18];
int d[100010];
int sum[6000010];
int ans[100010];
int tot;
int x,y;
int n,m;
int num;
int cnt;
struct miku
{
int x;
int y;
int z;
}a[100010];
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs(int x)
{
d[x]=d[f[x][0]]+1;
for(int i=1;i<=17;i++)
{
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x][0])
{
f[to[i]][0]=x;
dfs(to[i]);
}
}
}
int lca(int x,int y)
{
if(d[x]<d[y])
{
swap(x,y);
}
int dep=d[x]-d[y];
for(int i=0;i<=17;i++)
{
if((dep&(1<<i)))
{
x=f[x][i];
}
}
if(x==y)
{
return x;
}
for(int i=17;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
void updata(int rt)
{
if(ls[rt]&&rs[rt])
{
sum[rt]=max(sum[ls[rt]],sum[rs[rt]]);
}
else if(ls[rt])
{
sum[rt]=sum[ls[rt]];
}
else if(rs[rt])
{
sum[rt]=sum[rs[rt]];
}
}
void insert(int &rt,int l,int r,int k,int v)
{
if(!rt)
{
rt=++cnt;
}
if(l==r)
{
sum[rt]+=v;
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
insert(ls[rt],l,mid,k,v);
}
else
{
insert(rs[rt],mid+1,r,k,v);
}
updata(rt);
}
void merge(int &rt,int x)
{
if(!rt||!x)
{
rt=rt+x;
return ;
}
sum[rt]+=sum[x];
merge(ls[rt],ls[x]);
merge(rs[rt],rs[x]);
updata(rt);
}
int query(int rt,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
if(sum[rt]>0)
{
return l;
}
return 0;
}
if(sum[ls[rt]]>=sum[rs[rt]])
{
return query(ls[rt],l,mid);
}
else
{
return query(rs[rt],mid+1,r);
}
}
void downdata(int x)
{
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x][0])
{
downdata(to[i]);
merge(root[x],root[to[i]]);
}
}
ans[x]=query(root[x],1,num);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
h[i]=a[i].z;
}
sort(h+1,h+1+m);
num=unique(h+1,h+1+m)-h-1;
for(int i=1;i<=m;i++)
{
int anc=lca(a[i].x,a[i].y);
a[i].z=lower_bound(h+1,h+1+num,a[i].z)-h;
insert(root[a[i].x],1,num,a[i].z,1);
insert(root[a[i].y],1,num,a[i].z,1);
insert(root[anc],1,num,a[i].z,-1);
if(anc!=1)
{
insert(root[f[anc][0]],1,num,a[i].z,-1);
}
}
downdata(1);
for(int i=1;i<=n;i++)
{
printf("%d\n",h[ans[i]]);
}
}
BZOJ3307雨天的尾巴——线段树合并的更多相关文章
- 【BZOJ3307】雨天的尾巴 线段树合并
[BZOJ3307]雨天的尾巴 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多 ...
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- P4556 雨天的尾巴 线段树合并
使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...
- bzoj 3307: 雨天的尾巴 线段树合并
题目大意: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.问完成所有发放后,每个点存放最多的是哪种物品. 题解: 首先我们为每一个节 ...
- [BZOJ3307] 雨天的尾巴-----------------线段树进阶
虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- 洛谷P4556 雨天的尾巴 线段树
正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...
- [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)
[BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...
- 雨天的尾巴(bzoj3307)(线段树合并+树上差分)
\(N\)个点,形成一个树状结构.有\(M\)次发放,每次选择两个点\(x,y\) 对于\(x\)到\(y\)的路径上(含\(x,y\))每个点发一袋\(Z\)类型的物品.完成 所有发放后,每个点存放 ...
随机推荐
- [06] Bean属性的注入
之前我们提到了Bean实例化的三种方式:构造器方式.静态工厂方式.普通工厂方式.那么对于Bean中的属性,又是如何进行注入的(依赖注入),这个篇章就来提一提. 1.先提提什么是"依赖注入&q ...
- 深入理解 JVM(上)
菜鸟拙见,望请纠正(首先:推荐一本书[链接:https://pan.baidu.com/s/15I062n5LPYtRmueAAUFuFA 密码:kyo1]) 一:JVM体系概述 1:JVM是运行在操 ...
- jetty 客服端 与服务端
jetty 服务端,客服端有请求buffter 检查 默认4kb 4096 客服端 HttpClient client=new HttpClient(); client.setRequestBuffe ...
- 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)
编者按:这篇文章来自简书的一个位博主Jeffbond,读了好几遍,翻译的质量比较高,原文链接:分布式一致性算法:Raft 算法(Raft 论文翻译),版权一切归原译者. 同时,第6部分的集群成员变更读 ...
- 关于小程序登录时获取openId和unionId走过的坑
目前的项目是在做小程序这方面的,接触过的人应该都知道,同一个微信开放平台下的相同主体的App.公众号.小程序的unionid是相同的,这样就可以锁定是不是同一个用户.微信针对不同的用户在不同的应用下都 ...
- OLED小记
1.点阵组成OLED,OLED中有一个GRAM区域,区域中的值直接刷新到屏幕上,对应关系是1bit对应一个像素点: 2.要点亮一个像素点,只需要将GRAM中的对应bit位写1即可.GRAM中是分页来管 ...
- 【强化学习】python 实现 q-learning 例三(例一改写)
本文作者:hhh5460 本文地址:https://www.cnblogs.com/hhh5460/p/10139738.html 例一的代码是函数式编写的,这里用面向对象的方式重新撸了一遍.好处是, ...
- Quartz.Net分布式任务管理平台(第二版)
前言:在Quartz.Net项目发布第一版后,有挺多园友去下载使用,我们通过QQ去探讨,其中项目中还是存在一定的不完善.所以有了现在这个版本.这个版本的编写完成其实有段时间了一直没有放上去.现在已经同 ...
- C_数据结构_递归实现累加
# include <stdio.h> long sum(int n) { //用递归实现: ) ; else ) + n; /* 用for循环实现: long s = 0; int i; ...
- 总结and规划
不知不觉中又过去了一年,马上就要读研究生了,因此有必要对自己进行必要的总结,以及对自己有个良好的规划. 首先,描述自己当前的心情——对未来充满了恐惧和焦虑. 马上大学就要毕业了,回首经历的大学生涯,似 ...