Hdu 6133 启发式合并

今(yi)天(zhi)被NJU(suoyou)的多校虐得满地找牙。。
第一次写启发式合并。。
大概就是大的子树只更新一次,把小的子树往大的里面抽插(233)。。
然后就可以了。。
唯一的问题是我代码能力十分捉急,写出了n个bug。。

//启发式合并get
//NJU很牛逼啊
//这个sumofsum树状数组也很套路啊
//我TM好菜菜啊

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int a[105000];
int id[105000];
int b[105000];
ll num[105000];
ll sum[105000];
int lson[105000];
int rson[105000];
int n;

int cmp(int x, int y){
    if(a[x]==a[y])return x<y;
    return a[x]<a[y];
}

struct edge{
    int to, next;
}e[205000];

int head[105000];
int cnt;
int siz[105000];
ll ans[105000];
ll tmp;
ll tot;

void init(){
    tmp=0;
    memset(lson, -1, sizeof(lson));
    memset(rson, -1, sizeof(rson));
    memset(ans, 0, sizeof(ans));
    memset(num, 0, sizeof(num));
    memset(sum, 0, sizeof(sum));
    memset(head, -1, sizeof(head));
    cnt=0;
}

void add(int u, int v){
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs(int u, int fa){
    siz[u]=1;
    for(int i=head[u];~i;i=e[i].next){
        if(e[i].to!=fa){
            dfs(e[i].to, u);
            siz[u]+=siz[e[i].to];
            if(rson[u]==-1)rson[u]=e[i].to;
            else {
                if(siz[e[i].to]>siz[rson[u]]){
                    lson[u]=rson[u];
                    rson[u]=e[i].to;
                }
                else {
                    lson[u]=e[i].to;
                }
            }
        }
    }
}

int lowbit(int x){
    return x&(-x);
}

void update(ll f[], int pos, int val){
    while(pos<=tot){
        f[pos]+=val;
        pos+=lowbit(pos);
    }
}

ll query(ll f[], int pos){
    ll ans=0;
    while(pos){
        ans+=f[pos];
        pos-=lowbit(pos);
    }
    return ans;
}

void add(int u){
    tmp+=(query(num, tot)-query(num, b[u]))*a[u];
    tmp+=query(sum, b[u])+a[u];
    update(num, b[u], 1);
    update(sum, b[u], a[u]);
}

void del(int u){
    tmp-=(query(num, tot)-query(num, b[u]))*a[u];
    tmp-=query(sum, b[u]);
    update(num, b[u], -1);
    update(sum, b[u], -a[u]);
}

void addtree(int u){
    add(u);
    if(lson[u]!=-1)addtree(lson[u]);
    if(rson[u]!=-1)addtree(rson[u]);
}

void deltree(int u){
    del(u);
    if(lson[u]!=-1)deltree(lson[u]);
    if(rson[u]!=-1)deltree(rson[u]);
}

void dfs1(int u){
    if(lson[u]==-1){
        if(rson[u]==-1){
            add(u);
            ans[u]=tmp;
            return ;
        }
        dfs1(rson[u]);
        add(u);
        ans[u]=tmp;
        return;
    }
    dfs1(lson[u]);
    deltree(lson[u]);
    dfs1(rson[u]);
    addtree(lson[u]);
    add(u);
    ans[u]=tmp;
    return ;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        init();
        scanf("%d", &n);
        for(int i=1;i<=n;i++){
            scanf("%d", &a[i]);
            id[i]=i;
        }
        sort(id+1, id+1+n, cmp);

        b[id[1]]=1;
        for(int i=2;i<=n;i++){
            if(a[id[i]]==a[id[i-1]])b[id[i]]=b[id[i-1]];
            else b[id[i]]=b[id[i-1]]+1;
        }
        tot=b[id[n]];

        for(int i=1;i<n;i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        dfs(1, 0);
        dfs1(1);
        for(int i=1;i<=n;i++)printf("%lld ", ans[i]);
        printf("\n");
    }
}

猜你喜欢

转载自blog.csdn.net/mrbird_to_fly/article/details/77344450