1. 程式人生 > >hdu 6133---Army Formations(啟發式合並+樹狀數組)

hdu 6133---Army Formations(啟發式合並+樹狀數組)

題解 lld logs utf bat spi exactly ida head

題目鏈接

Problem Description > Stormtroopers were the assault/policing troops of the Galactic Empire. Dissenting citizens referred to them as bucketheads, a derogatory nickname inspired by the bucket-shaped helmets of stormtroopers. They wore white armor made from plastoid over a black body glove which, in addition to creating an imposing image, was outfitted with a wide array of survival equipment and temperature controls that allowed its wearer to survive in most environments, and were designed to disperse blaster bolt energy. As members of the Stormtrooper Corps, an independent branch that operated under the Imperial Army, stormtroopers represented the backbone of the Imperial Military—trained for total obedience to the command hierarchy, as well as absolute loyalty to Emperor Sheev Palpatine and the Imperial regime. Stormtroopers were trained at Imperial Academies, and used a variety of weapons.
>
> --- Wookieepedia

Though being cruel and merciless in the battlefields, the total obedience to the command hierarchy makes message delivering between Stormtroopers quite inefficient, which finally caused the escape of Luke Skywalker, the destroy of the Death Star, and the collapse of the Galactic Empire.

In particular, the hierarchy of Stormtroopers is defined by a *binary tree*. Everyone in the tree has at most two direct subordinates and exactly one direct leader, except the first (numbered 1) Stormtrooper, who only obey the order of the Emperor.

It has been a time-consuming task for the Stormtroopers to input messages into his own log system. Suppose that the i
-th Stormtrooper has a message of length ai, which means that it costs ai time to input this message into a log system. Everyone in the hierarchy has the mission of collecting all messages from his subordinates (a direct or indirect children in the tree) and input thses messages and his own message into his own log system.

Everyone in the hierarchy wants to optimize the process of inputting. First of all, everyone collects the messages from all his subordinates. For a Stormtrooper, starting from time 0, choose a message and input it into the log system. This process proceeds until all messages from his subordinates and his own message have been input into the log system. If a message is input at time t, it will induce t units of penalty.

For every Stormtrooper in the tree, you should find the minimum penalty.

Input The first line of the input contains an integer T, denoting the number of test cases.

In each case, there are a number n (1n105) in the first line, denoting the size of the tree.

The next line contains n integers, the i-th integer denotes ai (0ai108), the i-th Stormtrooper’s message length.

The following n1 lines describe the edges of the tree. Each line contains two integers u,v (1u,vn), denoting there is an edge connecting u and v.
Output For each test case, output n space-separated integers in a line representing the answer. i-th number is the minimum penalty of gathering messages for i-th Stormtrooper.
Sample Input 1 3 1 2 3 1 2 2 3 Sample Output 10 7 3 題意:該校出題題目太長了,而且表達的不是很清楚,太難理解了。 該題簡而言之:有一個由 n 個節點構成的二叉樹,每個節點上有一個權值wi,求所有節點的一個計算值。對於某個節點來說,以它為根節點的子樹的所有的節點的值構成的序列的前綴和的和,即為這個節點的計算值,對於每個節點求最小的計算值,那麽很明顯貪心,把這個序列從小到大排序,然後再就算前綴和的和。 思路:官方題解說是啟發式合並,我不懂什麽是啟發式,我看了別人寫的代碼後,我的理解是對於左右子樹合並時,把小的子樹合並到大的子樹中去,這樣復雜度較小,我覺得這個過程就是應用了啟發式思想。 本題思路沒什麽好說的,只想簡單說一下合並,本題中的計算是由樹狀數組完成的,對於每次在已有節點上添加一個節點x時,這些數的前綴和的和變化為:tmp+=大於w[x]的數個數*w[x]+w[x]+小於w[x]的所有數的和。 代碼如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int w[N];
int val[N],id[N];
int sz[N],lson[N],rson[N],tot;
vector<int>e[N];
LL num[N],sum[N];
LL ans[N],tmp;

int calSize(int now,int pre)
{
    sz[now]=1;
    for(int j=0;j<e[now].size();j++)
    {
        int to=e[now][j];
        if(to==pre) continue;
        if(!lson[now]) lson[now]=to;
        else rson[now]=to;
        sz[now]+=calSize(to,now);
    }
    if(lson[now]&&rson[now]&&sz[lson[now]]>sz[rson[now]])
    swap(lson[now],rson[now]);
    return sz[now];
}
int lowbit(int x)
{
    return x&(-x);
}
void update(LL *a,int x,int y)
{
    while(x<=tot)
    {
        a[x]+=(LL)y;
        x+=lowbit(x);
    }
}
LL query(LL *a,int x)
{
    LL r=0;
    while(x)
    {
       r+=a[x];
       x-=lowbit(x);
    }
    return r;
}

void add(int x)
{
    tmp+=(query(num,tot)-query(num,id[x]))*(LL)w[x]+(LL)w[x];
    tmp+=query(sum,id[x]);
    update(num,id[x],1);
    update(sum,id[x],w[x]);
}
void del(int x)
{
    update(num,id[x],-1);
    update(sum,id[x],-w[x]);
    tmp-=(query(num,tot)-query(num,id[x]))*(LL)w[x]+(LL)w[x];
    tmp-=query(sum,id[x]);
}
void cle(int x)
{
    del(x);
    if(lson[x]) cle(lson[x]);
    if(rson[x]) cle(rson[x]);
}
void validate(int x)
{
    add(x);
    if(lson[x]) validate(lson[x]);
    if(rson[x]) validate(rson[x]);
}
void dfs(int now)
{
   if(!lson[now])
   {
       ans[now]=(LL)w[now];
       add(now);
       return ;
   }
   dfs(lson[now]);
   if(rson[now])
   {
       cle(lson[now]);
       dfs(rson[now]);
       validate(lson[now]);
   }
   add(now);
   ans[now]=tmp;
}
int main()
{
    int T; cin>>T;
    while(T--)
    {
        int n; scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&w[i]);
            val[i]=w[i];
            e[i].clear();
            num[i]=sum[i]=0;
            lson[i]=rson[i]=0;
        }
        sort(val+1,val+n+1);
        tot=unique(val+1,val+n+1)-val-1;
        for(int i=1;i<=n;i++)
        {
            id[i]=lower_bound(val+1,val+tot+1,w[i])-val;
        }
        for(int i=1;i<n;i++)
        {
            int u,v; scanf("%d%d",&u,&v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        calSize(1,-1);
        tmp=0;
        dfs(1);
        for(int i=1;i<=n;i++)
            printf("%lld ",ans[i]);
        puts("");
    }
    return 0;
}

hdu 6133---Army Formations(啟發式合並+樹狀數組)