题目背景
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
题目描述
首先村落里的一共有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
用树上差分,对于(x,y)这条路径,则在x,y处+1,在lca,fa(lca)处−1,然后再用线段树合并即可。
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200005,M=200000;
int n,m,Cnt,tot;
int Head[N],v[N<<1],Next[N<<1];
int dep[N],ans[N],root[N],fa[N][25],lc[N<<5],rc[N<<5];
pair<int,int>Max[N<<5];
void add(int x,int y){
Cnt++;
Next[Cnt]=Head[x];
Head[x]=Cnt;
v[Cnt]=y;
}
void dfs(int x){
for(int i=1;i<=20;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
}
for(int i=Head[x];i;i=Next[i]){
int k=v[i];
if(k!=fa[x][0]){
fa[k][0]=x;
dep[k]=dep[x]+1;
dfs(k);
}
}
}
int lca(int x,int y){
int i;
if(dep[x]<dep[y]){
swap(x,y);
}
for(i=20;~i;--i){
if(dep[fa[x][i]]>=dep[y]){
x=fa[x][i];
}
}
if(x==y){
return x;
}
for(i=20;~i;--i){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
void insert(int &root,int l,int r,int pos,int num){
if(!root){
root=++tot;
}
if(l==r){
Max[root]=make_pair(Max[root].first+num,-pos);
return;
}
int mid=(l+r)>>1;
if(pos<=mid){
insert(lc[root],l,mid,pos,num);
}
else{
insert(rc[root],mid+1,r,pos,num);
}
Max[root]=max(Max[lc[root]],Max[rc[root]]);
}
int Merge(int x,int y,int l,int r){
if(!x){
return y;
}
if(!y){
return x;
}
int mid=(l+r)>>1;
if(l==r){
Max[x].first+=Max[y].first;
return x;
}
lc[x]=Merge(lc[x],lc[y],l,mid);
rc[x]=Merge(rc[x],rc[y],mid+1,r);
Max[x]=max(Max[lc[x]],Max[rc[x]]);
return x;
}
void Dfs(int x){
int i,k;
for(i=Head[x];i;i=Next[i]){
k=v[i];
if(k!=fa[x][0]){
Dfs(k);
root[x]=Merge(root[x],root[k],1,M);
}
}
ans[x]=-Max[root[x]].second;
}
int main(){
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dep[1]=1;
dfs(1);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
insert(root[x],1,M,z,1);
insert(root[y],1,M,z,1);
insert(root[lca(x,y)],1,M,z,-1);
insert(root[fa[lca(x,y)][0]],1,M,z,-1);
}
Dfs(1);
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
return 0;
}
P4556 雨天的尾巴
猜你喜欢
转载自www.cnblogs.com/ukcxrtjr/p/11311643.html
今日推荐
周排行