Description
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成所有发放后,每个点存放最多的是哪种物品。
Input
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题
Output
输出有N行每i行的数字表示第i个点存放最多的物品是哪一种,如果有多种物品的数量一样,输出编号最小的。如果某个点没有物品则输出0
Sample Input
20 50
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
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
Sample Output
87
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
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
题解
一道很强的树链剖分+线段树+差分的题。
首先我们把x到y上都放上物品z转化到一部分一部分的(通过树剖),每次跳到top位置,然后把top位置+1,x位置的下一个位置(即dfs序的下一个)-1;这样有什么用呢,这样可以最后遍历dfs序,直接看每个点。对每一个点建一颗线段树,那怎么记录这个点有什么物品放在这了呢?在跑x到y的路径的时候,(假设跑x)我们在top[x]建一条x到z的边,权值为1,x+1到z建边,权值为-1。这样我们就可以通过遍历这个点的所有边就可以知道有几种物品了。
/*
差分+线段树+树链剖分
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=100010;
int n,m;
int pre[N*30],last[N*30],other[N*30],num,w[N*30];
int dep[N],dfn[N],fa[N],son[N],size[N],top[N],cnt,tot,bl[N];
int ans[N],a[N];
map<int,int>mp;
inline void read(int &x){
x=0;char ch;int res=1;ch=getchar();
while(!(ch>='0'&&ch<='9')) {
if(ch=='-') res=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x=x*res;
}
inline void add(int x,int y){
num++;
pre[num]=last[x];
last[x]=num;
other[num]=y;
}
inline void insert(int x,int y,int z){
num++;
pre[num]=last[x];
last[x]=num;
other[num]=y;
w[num]=z;
}
void dfs1(int x){
size[x]=1;
for(int i=last[x];i;i=pre[i]){
int v=other[i];
if(v!=fa[x]){
fa[v]=x;
dep[v]=dep[x]+1;
dfs1(v);
size[x]+=size[v];
if(!son[x]||size[son[x]]<size[v])
son[x]=v;
}
}
}
void dfs2(int x,int tp){
dfn[x]=++cnt;bl[cnt]=x;top[x]=tp;
if(son[x]){
dfs2(son[x],tp);
}
for(int i=last[x];i;i=pre[i]){
int v=other[i];
if(v!=fa[x]&&v!=son[x])
dfs2(v,v);
}
}
struct tree{
int mx,type,l,r;
}t[N<<2];
inline void update(int x){
t[x].mx=-1;
if(t[x<<1].mx>t[x].mx||(t[x<<1].mx==t[x].mx&&a[t[x].type]>a[t[x<<1].type])) t[x].mx=t[x<<1].mx,t[x].type=t[x<<1].type;
if(t[x<<1|1].mx>t[x].mx||(t[x<<1|1].mx==t[x].mx&&a[t[x].type]>a[t[x<<1|1].type])) t[x].mx=t[x<<1|1].mx,t[x].type=t[x<<1|1].type;
return ;
}
void build(int x,int l,int r){
t[x].l=l;t[x].r=r;
if(l==r){
t[x].type=l;
return ;
}
int mid=(l+r)>>1;
build(x*2,l,mid);build(x*2+1,mid+1,r);
update(x);
}
void change(int x,int pos,int y){
//printf("t[x].mx=%d\n",t[x].mx);
if(t[x].l>pos||t[x].r<pos) return ;
if(t[x].l==pos&&t[x].r==pos){
t[x].mx+=y;
return ;
}
change(x<<1,pos,y);change(x<<1|1,pos,y);
update(x);
}
int main(){
int x,y,z;
read(n),read(m);
for(int i=1;i<n;i++){
read(x),read(y);
add(x,y);add(y,x);
}
dfs1(1),dfs2(1,1);
tot=0;
memset(last,0,sizeof(last));num=0;
for(int i=1;i<=m;i++){
read(x),read(y),read(z);
if(!mp[z]) mp[z]=++tot,a[tot]=z;
z=mp[z];
int f1=top[x],f2=top[y];
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
insert(dfn[f1],z,1);insert(dfn[x]+1,z,-1);//记录每个点的信息,非常常用
x=fa[f1];f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
insert(dfn[x],z,1);insert(dfn[y]+1,z,-1);
}
build(1,1,tot);
for(int i=1;i<=n;i++){
for(int j=last[i];j;j=pre[j]) {
//printf("w[j]=%d\n",w[j]);
change(1,other[j],w[j]);
}
ans[bl[i]]=t[1].mx?t[1].type:0;
}
for(int i=1;i<=n;i++) printf("%d\n",a[ans[i]]);
return 0;
}