hdu 6133 树状数组+分类讨论

来源:互联网 发布:中行外汇行情分析软件 编辑:程序博客网 时间:2024/06/18 14:43

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

首先这是个假题解。。只是提供一个思路。。。数据不强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 secondtypedef 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("");    }}


原创粉丝点击