AlenaNuna

导航

线段树合并 || BZOJ 5457: 城市

题面:https://www.lydsy.com/JudgeOnline/problem.php?id=5457

题解:

线段树合并,对于每个节点维护sum(以该节点为根的子树中最大的种类和)和kind(以该节点为根的子树中种类和最大的种类)即可。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=(4e5)+50;
 7 int N,M,U,V,num_edge=0,edge_head[maxn],root[maxn];
 8 int num_treenode=0;
 9 struct Edge{int to,nx;}edge[maxn<<1];
10 inline void Add_edge(int from,int to){
11     edge[++num_edge].nx=edge_head[from];
12     edge[num_edge].to=to;
13     edge_head[from]=num_edge;
14     return;
15 }
16 struct Tree{int lc,rc,l,r,sum,kd;}tr[maxn*20];
17 inline void Pushup(int x){
18     int lc=tr[x].lc,rc=tr[x].rc;
19     if(tr[lc].sum>=tr[rc].sum){
20         tr[x].sum=tr[lc].sum;
21         tr[x].kd=tr[lc].kd;
22     }
23     else {
24         tr[x].sum=tr[rc].sum;
25         tr[x].kd=tr[rc].kd;
26     }
27     return;
28 }
29 inline void Build(int x,int l,int r,int q,int s){
30     tr[x].l=l;tr[x].r=r;int mid=(l+r)>>1;
31     if(l==r&&l==q){
32         tr[x].kd=q;
33         tr[x].sum=s;
34         return;
35     }
36     if(q<=mid)Build(tr[x].lc=++num_treenode,l,mid,q,s);
37     else Build(tr[x].rc=++num_treenode,mid+1,r,q,s);
38     Pushup(x);
39     return;
40 }
41 struct A_{int kd,sum;}A[maxn];
42 inline int Merge(int u,int v){
43     if(!u)return v;
44     if(!v)return u;
45     int l=tr[u].l,r=tr[u].r;
46     if(l==r){
47         tr[u].sum+=tr[v].sum;
48         return u;
49     }
50     tr[u].lc=Merge(tr[u].lc,tr[v].lc);
51     tr[u].rc=Merge(tr[u].rc,tr[v].rc);
52     Pushup(u);
53     return u;
54 }
55 inline void Dfs(int x,int fa){
56     for(int i=edge_head[x];i;i=edge[i].nx){
57         int y=edge[i].to;
58         if(y!=fa){
59             Dfs(y,x);
60             Merge(root[x],root[y]);
61         }
62     }
63     return;
64 }
65 int main(){
66     scanf("%d%d",&N,&M);
67     for(int i=1;i<N;i++){
68         scanf("%d%d",&U,&V);
69         Add_edge(U,V);Add_edge(V,U);
70     }
71     for(int i=1;i<=N;i++){
72         scanf("%d%d",&A[i].kd,&A[i].sum);
73         Build(root[i]=++num_treenode,1,M,A[i].kd,A[i].sum);
74     }
75     Dfs(1,0);
76     for(int i=1;i<=N;i++)printf("%d %d\n",tr[root[i]].kd,tr[root[i]].sum);
77     return 0;
78 }

By:AlenaNuna

posted on 2019-03-13 21:03  AlenaNuna  阅读(124)  评论(0编辑  收藏  举报