【专题属性】树状数组

High-level ancients(UESTC_1653)

题目大意:

给一棵多叉树。初始所有结点的权值为0
有两种操作
1.add
ADD u val
以u为根的子树
u的权值+val
u的下一层儿子权值+val+1
下下一层儿子权值+val+2
类推...
2.Query
Q x
询问以x为根的子树(包含x)的权值和

结点个数N<=50000 询问个数 P<=100000 0<=val<=1000


题解:

dfs一遍整棵树  记录进结点和出结点的时间戳 得到dfs序 A

idx[u] idy[u] u进出的时间戳

tot[u] 以u为根的结点个数

tot_h[u] 以u为根的所有子结点(包括u)高度和

val[]       每在u添加一个x,val[idx[u]]+=x-h[u]

                           val[idy[u]]-=x-h[u];

time_u[u]   每在u添加一个x, time_u[idx[u]]+=1

                             time_u[idy[u]]-=1

sum_u[idx[u]] 每在u添加一个x,sum_u+=(x-h[u])*tot[u]+tot_h[u];

ANS=tot_h[u]*Sigma_time(1,idx[fa[u]])+Sigma_val(1,idx[fa[u]])*tot[u]+Sigma_sum(idx[u],idy[u]-1);

询问u的答案就是 ANS

因为只涉及修改和求和操作。维护3个树状数组即可。


#include 
#include 
#include 
#include 
#define maxn 50050

using namespace std;

int id;
long long fa[maxn],q[maxn*2],tot[maxn],h[maxn],idx[maxn],idy[maxn],tot_h[maxn];
long long  val[maxn*2],time_u[maxn*2],sum_u[maxn*2];
vector  graph[maxn];

void dfs(int u,int deep)
{
    tot_h[u]=h[u]=deep;
    q[++id]=u;
    idx[u]=id;
    tot[u]=1;

    for (int i=0;i0)
   {
       tot+=a[x];
       x-=lowbit(x);
   }
   return tot;
}


int main()
{
    int tt,cal=0;
    scanf("%d",&tt);
    while (tt--)
    {
        cal++;
        printf("Case #%d:\n",cal);
        int n,m;
        scanf("%d%d",&n,&m);

        for (int i=1;i<=n;i++)
        graph[i].clear();

        for (int i=2;i<=n;i++)
        {
            scanf("%lld",&fa[i]);
            graph[fa[i]].push_back(i);
        }

        id=0;
        dfs(1,1);
        memset(val,0,sizeof(val));
        memset(sum_u,0,sizeof(sum_u));
        memset(time_u,0,sizeof(time_u));
        fa[1]=0;idx[0]=idy[0]=0;

        while (m--)
        {
            char str[2];
            scanf("%s",str);
            if (str[0]=='Q')
            {
                int u;
                scanf("%d",&u);
                long long ans;

                ans=tot_h[u]*sum(idx[fa[u]],time_u)+sum(idx[fa[u]],val)*tot[u]+sum(idy[u]-1,sum_u)-sum(idx[u]-1,sum_u);
                printf("%lld\n",ans);
            } else
            {
                int u,x;
                scanf("%d%d",&u,&x);
                add(idx[u],x-h[u],val);
                add(idy[u],-x+h[u],val);
                add(idx[u],1,time_u);
                add(idy[u],-1,time_u);
                add(idx[u],(x-h[u])*tot[u]+tot_h[u],sum_u);
            }
        }

    }
    return 0;
}





你可能感兴趣的:(总结)