bzoj 5457 城市

Description

有n座城市,m个民族。这些城市之间由n-1条道路连接形成了以城市1为根的有根树。每个城市都是某一民族的聚居
地,Master知道第i个城市的民族是A_i,人数是B_i。为了维护稳定,Master需要知道某个区域内人数最多的民族
。他向你提出n个询问,其中第i个询问是:求以i为根的子树内,人数最多的民族有是哪个,这个民族有多少人。
如果子树内人数最多的民族有多个,输出其中编号最小的民族。
 
 

 

Input

共有2*n行。
第一行有两个整数n, m。
接下来n-1行,每行有两个整数u, v,表示一条连接u和v的道路。
接下来n行,第i行有两个整数A_i, B_i。
n<=400000,m<=n,1<=A_i<=m,0<=B_i<=1000。
 
 

 

Output

共有n行。
第i行两个整数x, y,分别表示以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
 
思路: 从叶子开始往上不断的进行线段树合并。 用了一个pair,比较方便。  
 1 #include<bits/stdc++.h>
 2 using namespace std;  
 3 #define R register int 
 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 
 5 #define Rep(i,a,b) for(R i=a;i>=b;i--)  
 6 #define ms(i,a)    memset(a,i,sizeof(a)) 
 7 #define gc()       getchar() 
 8 #define mid        (l+r>>1) 
 9 #define pii        pair<int,int>  
10 #define fi         first 
11 #define se         second  
12 template<class T>void read(T &x){
13     x=0; char c=0; 
14     while (!isdigit(c)) c=gc();  
15     while (isdigit(c)) x=x*10+(c^48),c=gc();  
16 }
17 int const N=400000+3; 
18 struct Edge{
19     int to,nt;  
20 }E[N<<1];  
21 int H[N],cnt,n,m,a[N],b[N],rt[N],lc[N*30],rc[N*30],sum;  
22 pii ans[N],mx[N*30];  
23 void add(int a,int b){
24     E[cnt]=(Edge){b,H[a]}; H[a]=cnt++; 
25 }
26 int merge(int x,int y,int l,int r){
27     if(!x) return y;  
28     if(!y) return x;  
29     if(l==r) mx[x].fi+=mx[y].fi;  
30     else {
31         lc[x]=merge(lc[x],lc[y],l,mid);  
32         rc[x]=merge(rc[x],rc[y],mid+1,r);  
33         mx[x]=max(mx[lc[x]],mx[rc[x]]);  
34     }
35     return x; 
36 }
37 void update(int &x,int l,int r,int a,int b){
38     if(!x) x=++sum;  
39     if(l==r){
40         mx[x].fi+=b;mx[x].se=-a;  
41         return ; 
42     }
43     if(a<=mid) update(lc[x],l,mid,a,b);  
44     else update(rc[x],mid+1,r,a,b);  
45     mx[x]=max(mx[lc[x]],mx[rc[x]]);  
46 }
47 void dfs(int x,int fa){
48     for(R i=H[x];i!=-1;i=E[i].nt){
49         int v=E[i].to;  
50         if(v==fa) continue;  
51         dfs(v,x); 
52         rt[x]=merge(rt[x],rt[v],1,m);  
53     }
54     update(rt[x],1,m,a[x],b[x]);  
55     ans[x]=mx[rt[x]];  
56 }
57 int main(){
58     read(n); read(m);
59     ms(-1,H);    
60     rep(i,1,n-1){
61         int x,y;
62         read(x); read(y);  
63         add(x,y); add(y,x);   
64     }
65     rep(i,1,n) read(a[i]),read(b[i]);  
66     dfs(1,0);  
67     rep(i,1,n) printf("%d %d\n",-ans[i].se,ans[i].fi);  
68     return 0; 
69 }
View Code

 

 
posted @ 2019-03-17 08:53  zjxxcn  阅读(282)  评论(0编辑  收藏  举报