[dsu on tree]Special_Containment_Procedures

题目描述
TAIYU把OJ上的所有题都建成了一棵树(虽然我也不知道他怎么建的)在一颗子树里面的题大多都有一些共同点。
当然,1号点是根结点,(一猜就是A+B Problem) 每一道题都有一个难度系数 ai 定义f(i)为i的子树的出现次数最
多的难度的和。 举个例子:如果i子树内题目的难度为:
 1 1 2 3 3 5
则f(i)等于1+3=4; 你需要输出 f(1),f(2),f(3),f(n)
输入描述
第一行一个整数表示n 第二行n个数,表示i节点的难度系数ci 第3行至第n+1行,每行2个数u,v,表示u,v之间连边
输出描述
一行n个数,第i个数表示f(i)

Solution

dsu on tree     https://www.cnblogs.com/zwfymqz/p/9683124.html

或 线段树合并  https://www.cnblogs.com/Mychael/p/8665589.html

都是nlogn  直接启发式合并n*logn*logn 貌似也能过

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1e5+5;
 5 int n,c[N],ans[N];
 6 int num,last[N],nxt[2*N],ver[2*N];
 7 inline void add(int x,int y) {nxt[++num]=last[x]; last[x]=num; ver[num]=y;}
 8 
 9 int fa[N],siz[N],son[N];
10 void build(int x)
11  {siz[x]=1; 
12   for(int i=last[x];i;i=nxt[i])
13    {int y=ver[i];
14     if(y==fa[x]) continue;
15     fa[y]=x; build(y); 
16     siz[x]+=siz[y]; 
17     if(siz[son[x]]<siz[y]) son[x]=y;
18    }
19  }
20 int maxx,sum,cnt[N]; 
21 void update(int x,int son,int v)
22  {cnt[c[x]]+=v;
23   if(cnt[c[x]]>maxx) maxx=cnt[sum=c[x]];
24   else if(cnt[c[x]]==maxx)sum+=c[x];
25   for(int i=last[x];i;i=nxt[i])
26    {int y=ver[i];
27     if(y!=fa[x] && y!=son) 
28     update(y,0,v);
29    }
30  }
31 void dfs(int x)
32  {for(int i=last[x];i;i=nxt[i])
33    {int y=ver[i]; 
34     if(y!=son[x] && y!=fa[x]) dfs(y);
35    }
36   if(son[x]) dfs(son[x]);
37   update(x,son[x],1);
38   ans[x]=sum;
39   if(son[fa[x]]!=x) update(x,0,-1),maxx=sum=0; 
40  } 
41 int main()
42  {
43  scanf("%d",&n);    int x,y;
44  for(int i=1;i<=n;i++) scanf("%d",&c[i]);    
45      
46  for(int i=1;i<=n;i++) {scanf("%d%d",&x,&y); add(x,y); add(y,x); }
47  
48  build(1); dfs(1);    
49  for(int i=1;i<=n;i++) printf("%d ",ans[i]);
50 return 0;
51  }

 

posted @ 2019-11-12 08:09  YuXiaoze  阅读(486)  评论(0编辑  收藏  举报