zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Linux临时增加swap空间
    Build RPM package from source code
    svn installation
    svn merge详解
    VMware DRS概述及功能
    VMware Fault Tolerance 概述及功能
    VMware HA 特性
    VMware Storage VMotion概述及功能
    Windows1小时后关机命令
    WINDOWS2008 KMS 服务器安装及激活
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7405565.html
Copyright © 2011-2022 走看看