bzoj 5457 城市

题目大意:

树上每个点有种类$a_i$和数量$b_i$,求每个点的子树内数量最多的种类的数量和这个数量

思路:

显然是线段树合并裸题

学习一下$dsu \space on \space tree$ 主要就是保留重链信息 其余点暴力

多用几个函数

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define inf 2139062143
13 #define MAXN 400100
14 #define MOD 998244353
15 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
16 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
17 #define ren for(register int i=fst[x];i;i=nxt[i])
18 #define pb(i,x) vec[i].push_back(x)
19 #define pls(a,b) (a+b)%MOD
20 #define mns(a,b) (a-b+MOD)%MOD
21 #define mul(a,b) (1LL*(a)*(b))%MOD
22 using namespace std;
23 inline int read()
24 {
25     int x=0,f=1;char ch=getchar();
26     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
27     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
28     return x*f;
29 }
30 int n,m,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],t[MAXN],val[MAXN];
31 int sz[MAXN],hvs[MAXN],cnt,num[MAXN],ans[MAXN],res[MAXN],tmp;
32 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
33 void dfs(int x,int pa)
34 {
35     sz[x]=1;ren if(to[i]^pa)
36     {
37         dfs(to[i],x),sz[x]+=sz[to[i]];
38         if(sz[to[i]]>sz[hvs[x]]) hvs[x]=to[i];
39     }
40 }
41 void cheq(int &x,int y) {x=(num[y]>num[x]||(num[x]==num[y]&&y<x))?y:x;}
42 void Get(int x,int pa,int v)
43 {
44     num[t[x]]+=v*val[x];if(v>0) cheq(tmp,t[x]);
45     ren if(to[i]^pa) Get(to[i],x,v);
46 }
47 void dsu(int x,int pa,int v)
48 {
49     ren if(to[i]^pa&&to[i]^hvs[x]) dsu(to[i],x,0);
50     if(hvs[x]) dsu(hvs[x],x,1);
51     ren if(to[i]^pa&&to[i]^hvs[x]) Get(to[i],x,1);
52     num[t[x]]+=val[x];cheq(tmp,t[x]);ans[x]=tmp,res[x]=num[tmp];
53     if(!v) tmp=0,Get(x,pa,-1);
54 }
55 int main()
56 {
57     n=read(),m=read();int a,b;rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a);
58     rep(i,1,n) t[i]=read(),val[i]=read();
59     dfs(1,0);dsu(1,0,1);rep(i,1,n) printf("%d %d\n",ans[i],res[i]);
60 }
View Code

 

posted @ 2019-03-12 16:12  jack_yyc  阅读(127)  评论(0编辑  收藏  举报