1. 程式人生 > >[CF600E]Lomsat gelral

[CF600E]Lomsat gelral

題意翻譯

一棵樹有n個結點,每個結點都是一種顏色,每個顏色有一個編號,求樹中每個子樹的最多的顏色編號的和。

線段樹合併板子題,沒啥難度,注意開long long

不過這題$dsu$ $on$ $tree$確實更快

程式碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #define ls ch[node][0]
 4 #define rs ch[node][1]
 5 #define M 100010
 6 using namespace std;
 7 int n,m,num,cnt;
 8 int head[M],rt[M],co[M];
9 int ch[M<<7][2],v1[M<<7]; 10 long long v2[M<<7],ans[M]; 11 struct point{int to,next;}e[M<<1]; 12 void add(int from,int to) { 13 e[++num].next=head[from]; 14 e[num].to=to; 15 head[from]=num; 16 } 17 void update(int node) { 18 if(v1[ls]==v1[rs]) { 19
v1[node]=v1[ls];v2[node]=v2[ls]+v2[rs]; 20 } 21 else{ 22 if(v1[ls]>v1[rs]) v1[node]=v1[ls],v2[node]=v2[ls]; 23 else v1[node]=v1[rs],v2[node]=v2[rs]; 24 } 25 } 26 void insert(int &node,int l,int r,int x) { 27 if(!node) node=++cnt; 28 if(l==r) {
29 v1[node]=1,v2[node]=x;return; 30 }int mid=(l+r)/2; 31 if(x<=mid) insert(ls,l,mid,x); 32 else insert(rs,mid+1,r,x); 33 update(node); 34 } 35 int merge(int x,int y,int l,int r) { 36 if(!x||!y) return x+y; 37 int node=++cnt; 38 if(l==r) { 39 v1[node]=v1[x]+v1[y];v2[node]=l;return node; 40 } 41 int mid=(l+r)/2; 42 ch[node][0]=merge(ch[x][0],ch[y][0],l,mid); 43 ch[node][1]=merge(ch[x][1],ch[y][1],mid+1,r); 44 update(node);return node; 45 } 46 void dfs(int x,int fa) { 47 insert(rt[x],1,n,co[x]); 48 for(int i=head[x];i;i=e[i].next) { 49 int to=e[i].to; 50 if(to==fa) continue; 51 dfs(to,x); 52 rt[x]=merge(rt[x],rt[to],1,n); 53 } 54 ans[x]=v2[rt[x]]; 55 } 56 int main() { 57 scanf("%d",&n); 58 for(int i=1;i<=n;i++) scanf("%d",&co[i]); 59 for(int i=1;i<n;i++) { 60 int x,y;scanf("%d%d",&x,&y); 61 add(x,y),add(y,x); 62 } 63 dfs(1,0); 64 for(int i=1;i<=n;i++) printf("%lld ",ans[i]); 65 return 0; 66 }