hdu 6133 Army Formations(树状数组+启发式合并)

题目链接:hdu 6133 Army Formations

题意:

搞了一圈,最近就是让你输出每个点的答案,每个点的答案计算为将一该点为子树的全部的点的权值排序,求一下前缀和的前缀和。

题解:

由于是求前缀和的前缀和,考虑用树状数组,对于每插入一个数x,他的贡献为sum(x-1)+当前比他大的个数*x。

那么如果求树上每一个点的答案。

由于该树是一棵二叉树,所以我们先遍历每个节点的轻儿子(子节点数较小的儿子),再遍历重儿子,这样可以将节点数小的合并到大的。

然后总复杂度就是nlogn2

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=a;i<=b;++i)
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 const int N=1e5+7;
 8 int t,n,a[N],hsh[N],h_ed,x,y,size[N],S[N],top;
 9 ll sum[N],num[N],ans[N];
10 vector<int>g[N];
11 int tr[N][2],rnk[N];
12 
13 void dfs(int x,int fa)
14 {
15     size[x]=1;
16     for(int it:g[x])if(it!=fa)
17         dfs(it,x),size[x]+=size[it];
18     for(int it:g[x])if(it!=fa)
19     {
20         if(size[tr[x][1]]<size[it])tr[x][1]=it;
21         if(size[tr[x][0]]<size[tr[x][1]])swap(tr[x][0],tr[x][1]);
22     }
23 }
24 
25 inline void add(ll *C,int x,int v){while(x<=h_ed)C[x]+=v,x+=x&-x;}
26 inline ll ask(ll *C,int x){ll an=0;while(x)an+=C[x],x-=x&-x;return an;}
27 
28 ll insert(int idx)
29 {
30     ll val=0;
31     add(num,rnk[idx],1),add(sum,rnk[idx],a[idx]);
32     val+=(ll)a[idx]*(ask(num,h_ed)-ask(num,rnk[idx]-1));
33     val+=ask(sum,rnk[idx]-1);
34     return val;
35 }
36 
37 void remove(int idx)
38 {
39     add(num,rnk[idx],-1),add(sum,rnk[idx],-a[idx]);
40 }
41 
42 void dfs2(int x=1)
43 {
44     int l=top+1,r;
45     if(tr[x][0])dfs2(tr[x][0]);
46     r=top;
47     if(tr[x][1])
48     {
49         F(i,l,r)remove(S[i]);
50         dfs2(tr[x][1]);
51         ans[x]=ans[tr[x][1]];
52         F(i,l,r)ans[x]+=insert(S[i]);
53     }
54     else ans[x]=ans[tr[x][0]];
55     S[++top]=x,ans[x]+=insert(x);
56 }
57 
58 int main(){
59     scanf("%d",&t);
60     while(t--)
61     {
62         scanf("%d",&n),top=0;
63         mst(sum,0),mst(num,0),mst(tr,0),mst(ans,0);
64         F(i,0,n)g[i].clear();
65         F(i,1,n)scanf("%d",a+i),hsh[i]=a[i];
66         sort(hsh+1,hsh+1+n),h_ed=unique(hsh+1,hsh+1+n)-hsh-1;
67         F(i,1,n)rnk[i]=lower_bound(hsh+1,hsh+1+h_ed,a[i])-hsh;
68         F(i,2,n)
69         {
70             scanf("%d%d",&x,&y);
71             g[x].push_back(y);
72             g[y].push_back(x);
73         }
74         dfs(1,0),dfs2();
75         F(i,1,n)printf("%lld ",ans[i]);
76         puts("");
77     }
78     return 0;
79 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7405565.html