历史上有一个著名的王国

【题目描述】

历史上有一个著名的王国。它的所有城市互相连通并且构成一棵树。城市1

为首都也就是这棵树的根。

因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量

为0。当城市i 被加派了k 名士兵时。城市i 的所有子城市需要被加派k+1 名士

兵。这些子城市的所有子城市需要被加派k+2 名士兵。以此类推。

当然,加派士兵的同时,国王也需要不断了解当前的情况。于是他随时可

能询问以城市i 为根的子树中的所有城市共被加派了多少士兵。

你现在是国王的军事大臣,你能回答出国王的每个询问么?

【输入】

第一行,包含两个整数N,P 代表城市数量以及国王的命令的数量。

接下来的P 行,每行代表国王的一个命令,命令分两种

A X K 在城市X 加入K 个士兵

Q X 询问以城市X 为根的子树中所有士兵数量的和

【输出】

对于每个Q,输出答案。

【输入样例】

7 10

1 1 2 2 5 5

Q 1

A 2 1

Q 1

Q 2

Q 5

A 5 0

Q 5

A 3 1

Q 1

Q 2

【输出样例】

0

11

11

8

10

14

13

【数据范围】

对于50%的数据, 1<=N<=1000 1<=P<=300

对于100%的数据, 1<=N<=50000 1<=P<=100000 1<=X<=N 0<=K<=1000

题解

对以u为根的子树进行增加操作,即对以u为根的树上的每一个节点v增加k+dep[v]-dep[u]

其中k-dep[u]是这个操作的性质,而dep[v]是节点的性质,所以考虑分成两部分求解,用线段树维护两个值:total[u]和sum[u],分别表示对u节点操作了多少次和所有k-dep[u]的和,则

Query(u)=total[u]*sumdep[u]+sum[u]*size[u],其中sumdep[u]表示以u为根的子树的所有节点v的dep[v]的和,size[u]表示以u为根的子树的节点个数,可以用一遍dfs求出。

  1 #include<cstdio>
  2 #ifdef WIN32
  3 #define putlong(x) printf("%I64d
",x);
  4 #else
  5 #define putlong(x) printf("%lld
",x);
  6 #endif
  7 using namespace std;
  8 struct listnode
  9 {
 10     int dest;
 11     listnode *next;
 12 }adj[100001];
 13 int index=0,id[50001],pre[50001],post[50001],dep[50001];
 14 void dfs(int u)
 15 {
 16     index++;
 17     id[index]=u;
 18     pre[u]=index;
 19     for(listnode *i=adj[u].next;i;i=i->next)
 20     {    
 21         dep[i->dest]=dep[u]+1;
 22         dfs(i->dest);
 23     }
 24     post[u]=index;
 25 }
 26 long long totlazy[200001],sumlazy[200001],sumdep[200001],le,ri,ans[200001],aug,__ans;
 27 void init(int o,int l,int r)
 28 {
 29     if(l==r)
 30         sumdep[o]=dep[id[l]];
 31     else
 32     {
 33         int m=(l+r)>>1;
 34         init(o<<1,l,m);
 35         init(o<<1|1,m+1,r);
 36         sumdep[o]=sumdep[o<<1]+sumdep[o<<1|1];
 37     }
 38 }
 39 void query(int o,int l,int r)
 40 {
 41     if(le<=l&&ri>=r)
 42         __ans+=ans[o];
 43     else
 44     {
 45         int m=(l+r)>>1;
 46         totlazy[o<<1]+=totlazy[o];
 47         totlazy[o<<1|1]+=totlazy[o];
 48         sumlazy[o<<1]+=sumlazy[o];
 49         sumlazy[o<<1|1]+=sumlazy[o];
 50         ans[o<<1]+=totlazy[o]*sumdep[o<<1]+sumlazy[o]*(m-l+1);
 51         ans[o<<1|1]+=totlazy[o]*sumdep[o<<1|1]+sumlazy[o]*(r-m);
 52         totlazy[o]=0;
 53         sumlazy[o]=0;
 54         if(le<=m)query(o<<1,l,m);
 55         if(ri>m)query(o<<1|1,m+1,r);
 56     }
 57 }
 58 void update(int o,int l,int r)
 59 {
 60     if(le<=l&&ri>=r)
 61     {
 62         totlazy[o]++;
 63         ans[o]+=sumdep[o];
 64         sumlazy[o]+=aug;
 65         ans[o]+=aug*(r-l+1);
 66     }
 67     else
 68     {
 69         int m=(l+r)>>1;
 70         totlazy[o<<1]+=totlazy[o];
 71         totlazy[o<<1|1]+=totlazy[o];
 72         ans[o<<1]+=totlazy[o]*sumdep[o<<1];
 73         ans[o<<1|1]+=totlazy[o]*sumdep[o<<1|1];
 74         totlazy[o]=0;
 75         sumlazy[o<<1]+=sumlazy[o];
 76         sumlazy[o<<1|1]+=sumlazy[o];
 77         ans[o<<1]+=sumlazy[o]*(m-l+1);
 78         ans[o<<1|1]+=sumlazy[o]*(r-m);
 79         sumlazy[o]=0;
 80         if(le<=m)update(o<<1,l,m);
 81         if(ri>m)update(o<<1|1,m+1,r);
 82         ans[o]=ans[o<<1]+ans[o<<1|1];
 83     }
 84 }
 85 int main()
 86 {
 87     freopen("c.in","r",stdin);
 88     freopen("c.out","w",stdout);
 89     int n(0),p(0);
 90     scanf("%d%d",&n,&p);
 91     listnode *a=adj+n+1;
 92     for(int i=2;i<=n;i++)
 93     {
 94         int x(0);
 95         scanf("%d",&x);
 96         a->dest=i;
 97         a->next=adj[x].next;
 98         adj[x].next=a++;
 99     }
100     dfs(1);
101     init(1,1,n);
102     char buf[10];
103     while(p--)
104     {
105         int x(0),k(0);
106         scanf("%s%d",buf,&x);
107         le=pre[x];
108         ri=post[x];
109         if(buf[0]=='A')
110         {
111             scanf("%d",&k);
112             aug=k-dep[x];
113             update(1,1,n);
114         }
115         else if(buf[0]=='Q')
116         {
117             __ans=0;
118             query(1,1,n);
119             putlong(__ans);
120         }
121     }
122     return 0;
123 }
原文地址:https://www.cnblogs.com/JebediahKerman/p/6052151.html