题目背景
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
题目描述
首先村落里的一共有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。
输入输出样例
输入 #1复制
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
输出 #1复制
2
3
3
0
2
说明/提示
对于20%的数据,1 <= n, m <= 100
对于50%的数据,1 <= n, m <= 2000
对于100%的数据,1 <= n, m <= 100000, 1 <= a, b, x, y <= n, 1 <= z <= 100000
Vani
本来就是简单的 树剖+线段树合并+树上差分,但是x写成i,,TLE成sb。
这道题每次放一个区间,不难想到需要树上差分,然后每个点都需要合并,故我们要使用线段树合并。
然后树剖求一下lca就行了。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10,M=N*80;
int n,m,res[N],len;
int rt[N],mx[M],t[M],lc[M],rc[M],cnt;
int bl[N],f[N],sz[N],h[N],son[N],vis[N];
int head[N],nex[N<<1],to[N<<1],tot;
inline int read(){
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x;
}
inline void add(int a,int b){to[++tot]=b; nex[tot]=head[a]; head[a]=tot;}
void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(f[x]==to[i]) continue;
h[to[i]]=h[x]+1; f[to[i]]=x;
dfs1(to[i]); sz[x]+=sz[to[i]];
if(sz[to[i]]>sz[son[x]]) son[x]=to[i];
}
}
void dfs2(int x,int belong){
bl[x]=belong;
if(!son[x]) return ; dfs2(son[x],belong);
for(int i=head[x];i;i=nex[i])
if(h[to[i]]>h[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
inline int lca(int x,int y){
while(bl[x]!=bl[y]){
if(h[bl[x]]<h[bl[y]]) swap(x,y); x=f[bl[x]];
}
return h[x]>h[y]?y:x;
}
inline void push_up(int p){
if(mx[lc[p]]>=mx[rc[p]]) mx[p]=mx[lc[p]],t[p]=t[lc[p]];
else mx[p]=mx[rc[p]],t[p]=t[rc[p]];
}
void change(int &p,int l,int r,int x,int v){
if(x<l||x>r) return ;
if(!p) p=++cnt;
if(l==r){mx[p]+=v; t[p]=x; return ;}
int mid=l+r>>1;
if(x<=mid) change(lc[p],l,mid,x,v);
else change(rc[p],mid+1,r,x,v);
push_up(p);
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x^y;
if(l==r){mx[x]+=mx[y]; t[x]=l; return x;}
int mid=l+r>>1;
lc[x]=merge(lc[x],lc[y],l,mid);
rc[x]=merge(rc[x],rc[y],mid+1,r);
push_up(x);
return x;
}
void dfs(int x){
for(int i=head[x];i;i=nex[i]){
if(h[to[i]]<h[x]) continue;
dfs(to[i]); rt[x]=merge(rt[x],rt[to[i]],1,len);
}
if(mx[rt[x]]) res[x]=t[rt[x]];
}
signed main(){
n=read(),m=read();
for(int i=1,a,b;i<n;i++) a=read(),b=read(),add(a,b),add(b,a);
dfs1(1); dfs2(1,1);
len=100000;
for(int i=1,x,y,z;i<=m;i++){
x=read(),y=read(),z=read();
int fa=lca(x,y);
change(rt[x],1,len,z,1),change(rt[y],1,len,z,1);
change(rt[fa],1,len,z,-1);
if(f[fa]) change(rt[f[fa]],1,len,z,-1);
}
dfs(1);
for(int i=1;i<=n;i++) printf("%d\n",res[i]);
return 0;
}