Description
中二少年cenbo幻想自己统治着Euphoric Field。由此他开始了Endless Fantasy。
Euphoric Field有
n
n
座城市,个民族。这些城市之间由
n−1
n
−
1
条道路连接形成了以城市
1
1
为根的有根树。每个城市都是某一民族的聚居地,cenbo知道第i个城市的民族是,人数是
Bi
B
i
。为了维护稳定,cenbo需要知道某个区域内人数最多的民族。他向你提出
n
n
个询问,其中第个询问是:求以
i
i
为根的子树内,人数最多的民族有是哪个,这个民族有多少人。如果子树内人数最多的民族有多个,输出其中编号最小的民族。
Input
输入文件endless.in共有行。
第一行有两个整数
n,m
n
,
m
。
接下来
n−1
n
−
1
行,每行有两个整数
u,v
u
,
v
,表示一条连接
u
u
和的道路。
接下来
n
n
行,第i行有两个整数。
Output
输出文件endless.out共有
n
n
行。
第i行两个整数,分别表示以
i
i
为根的子树中人数最多的民族和它的人数。
Sample Input
8 6
1 2
1 3
2 4
4 5
3 6
5 7
1 8
2 8
2 5
1 1
3 1
6 7
5 6
1 10
4 6
Sample Output
2 13
1 10
5 6
1 10
1 10
5 6
1 10
4 6
Data Constraint
30%的数据,;
60%的数据,
n<=40000
n
<=
40000
;
100%的数据,
n<=400000,m<=n,1<=Ai<=m,0<=Bi<=1000
n
<=
400000
,
m
<=
n
,
1
<=
A
i
<=
m
,
0
<=
B
i
<=
1000
。
输入文件较大请使用读入优化。
分析:
我们给每个棵子树维护一个桶。
因为没有修改,且是给所有点询问。考虑启发式合并这个桶即可。父亲的桶从重儿子获得,其他子树暴力加上。先跑轻儿子,然后把桶清空(再跑一遍子树)即可。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
const int maxn=4e5+7;
using namespace std;
int n,m,cnt,x,y;
int a[maxn],b[maxn],size[maxn],ans[maxn][2],ls[maxn];
int h[maxn];
struct edge{
int y,next;
}g[maxn*2];
void add(int x,int y)
{
g[++cnt]=(edge){y,ls[x]};
ls[x]=cnt;
}
void dfs(int x,int fa)
{
size[x]=1;
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if (g[i].y==fa) continue;
dfs(y,x);
size[x]+=size[y];
}
}
void ins(int x,int y,int d,int op)
{
if (op==1)
{
h[x]+=y;
if ((h[x]>ans[d][1]) || ((h[x]==ans[d][1]) && (x<ans[d][0])))
{
ans[d][1]=h[x];
ans[d][0]=x;
}
}
else h[x]-=y;
}
void count(int x,int fa,int d,int op)
{
ins(a[x],b[x],d,op);
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if (y==fa) continue;
count(y,x,d,op);
}
}
void solve(int x,int fa)
{
int c=0;
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if (y==fa) continue;
if (size[y]>size[c]) c=y;
}
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if ((y==fa) || (y==c)) continue;
solve(y,x);
count(y,x,x,0);
}
if (c) solve(c,x),ans[x][1]=ans[c][1],ans[x][0]=ans[c][0];
ins(a[x],b[x],x,1);
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if ((y==fa) || (y==c)) continue;
count(y,x,x,1);
}
}
int main()
{
freopen("endless.in","r",stdin);
freopen("endless.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i=1;i<=n;i++) scanf("%d %d",&a[i],&b[i]);
dfs(1,0);
solve(1,0);
for (int i=1;i<=n;i++) printf("%d %d\n",ans[i][0],ans[i][1]);
}