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 }