hdu 6133 树状数组+分类讨论

题意:。。比较复杂,就是一个树有点权,一个点的答案是子树的所有点权的前缀和的和(贪心思想转换后的题意),问所有答案。

首先这是个假题解。。只是提供一个思路。。。数据不强AC了。。。

思路:标解是个启发式合并。。这里尝试另一种做法(因为不会),平均时间复杂度是nlogn^2。(数据弱。。)考虑合并操作复杂,我们可以分为合并暴力,单个儿子直接得答案两种操作解决问题。(看起来很玄学。。),事实上是这样的,单个儿子的时间复杂度不用解释,肯定是正确的,我们只要维护子树离散化后的个数以及一个sum。对于暴力这部分。。其实也是一拍脑子想出来的。。首先有一个二叉结点我们就要暴力他的子树一次,当他是一个满二叉树的时候,整个排序的过程就类似一个归并树(事实上多一个sort的log),那么其实这个暴力就类似快排了,随机数据下时间复杂度是科学的。。


代码:

#include<bits/stdc++.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof(a))
#define bug puts("bug");
#define PB push_back
#define MP make_pair
#define X first
#define Y second
typedef unsigned long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+100;
const int mod=1e9+7;
using namespace std;
ll sum;
int id[maxn],L[maxn],R[maxn],x,y,n,t,tim,cnt[maxn];
ll b[maxn],a[maxn],hs[maxn],bit[maxn],ans[maxn],sbit[maxn];
vector<int> v[maxn];
void add(int x,int y){
    v[x].PB(y),v[y].PB(x);
}
int dfs(int x,int f){
    int ret=1;
    L[x]=tim++;
    b[L[x]]=a[x];
    for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=f)ret+=dfs(v[x][i],x);
    R[x]=tim-1;
    return cnt[x]=ret;
}
int lowbit(int x){
    return x&(-x);
}
void modify(int x,ll add,ll a[]){
    while(x<maxn){
        a[x]+=add;
        x+=lowbit(x);
    }
}
ll get_sum(ll x,ll a[]){
    ll ret=0;
    while(x!=0){
        ret+=a[x];
        x-=lowbit(x);
    }
    return ret;
}
void del(int x,int f){
    modify(id[x],-1,bit);
    modify(id[x],-a[x],sbit);
    for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=f)del(v[x][i],x);
}
void addx(int x,int f){
    modify(id[x],1,bit);
    modify(id[x],a[x],sbit);
    for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=f)addx(v[x][i],x);
}
void sl(int x,int f){
    vector<int> son;
    for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=f)son.PB(v[x][i]);
    int siz=son.size();
    if(siz==0)ans[x]=a[x];
    else if(siz==1){
        sl(son[0],x);
        ans[x]=ans[son[0]]+(get_sum(n+10,bit)-get_sum(id[x],bit))*a[x]+get_sum(id[x],sbit)+a[x];
    }
    else if(siz==2){
        int aa=0,bb=1;
        if(cnt[son[0]]>cnt[son[1]]) swap(aa,bb);
        sl(son[aa],x);
        del(son[aa],x);
        sl(son[bb],x);
        addx(son[aa],x);
        sort(b+L[x],b+R[x]+1);
        sum=0;
        for(int i=L[x];i<=R[x];i++)sum+=b[i],ans[x]+=sum;
    }
    modify(id[x],1,bit);
    modify(id[x],a[x],sbit);
}

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        tim=1;
        MEM(sbit,0),MEM(bit,0);MEM(ans,0);MEM(cnt,0);
        for(int i=0;i<=n+2;i++) v[i].clear();
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++) hs[i]=a[i];
        sort(hs+1,hs+n+1);
        int N=unique(hs+1,hs+n+1)-hs;
        for(int i=1;i<=n;i++) id[i]=lower_bound(hs+1,hs+N,a[i])-hs+1;
        for(int i=0;i<n-1;i++) scanf("%d%d",&x,&y),add(x,y);
        dfs(1,-1);
        sl(1,-1);
        for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
        puts("");
    }
}


原文地址:https://www.cnblogs.com/zhangxianlong/p/10672496.html