ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[树链剖分][树状数组] Luogu P3676 小清新数据结构题

2019-08-09 20:04:23  阅读:178  来源: 互联网

标签:pre 剖分 Luogu ll P3676 id add son top


题目描述

在很久很久以前,有一棵n个点的树,每个点有一个点权。

现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方和。

(题目不是很好懂,没看太懂的可以看看样例解释)

 

题解

 

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream> 
 4 #define ll long long
 5 #define sqr(x) (x)*(x)
 6 using namespace std;
 7 const ll N=2e5+10; 
 8 struct edge{ll from,to;}e[N<<1];
 9 ll n,m,cnt,ans,tot,w[N],c[N],fa[N],sz[N],id[N],pos[N],deep[N],son[N],top[N],head[N],sz1[N],sz2[N];
10 void add(ll x,ll y) { for (int i=x;i<=n;i+=i&(-i)) sz1[i]+=y,sz2[i]+=x*y; }
11 ll query(ll x) { ll r=0; for (ll i=x;i;i-=i&(-i)) r+=(x+1)*sz1[i]-sz2[i]; return r; }
12 void insert(ll x,ll y)
13 {
14     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt;
15     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt;
16 }
17 void dfs1(ll x)
18 {
19     deep[x]=deep[fa[x]]+1,sz[x]=1;
20     for (ll i=head[x];i;i=e[i].from) if (e[i].to!=fa[x])
21     {
22         fa[e[i].to]=x,dfs1(e[i].to),sz[x]+=sz[e[i].to],w[x]+=w[e[i].to];
23         if (sz[e[i].to]>sz[son[x]]) son[x]=e[i].to;
24     }
25     ans+=sqr(w[x]);
26 }
27 void dfs2(ll x,ll pre)
28 {
29     top[x]=pre;pos[id[x]=++tot]=x,add(id[x],w[x]-w[pos[tot-1]]);
30     if (son[x]) dfs2(son[x],pre);
31     for (ll i=head[x];i;i=e[i].from) if (fa[x]!=e[i].to&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to);
32 }
33 void modify(ll x,ll y)
34 {
35     ll l=0,r=0;
36     for (;x;x=fa[top[x]]) l+=id[x]-id[top[x]]+1,r+=query(id[x])-query(id[top[x]]-1),add(id[top[x]],y),add(id[x]+1,-y);
37     ans+=y*(y*l+(r<<1));
38 }
39 ll calc(ll u)
40 {
41     ll k=0,x=query(1),s=0;
42     for (;u;u=fa[top[u]]) k+=id[u]-id[top[u]]+1,s+=query(id[u])-query(id[top[u]]-1);
43     return ans+x*((k+1)*x-(s<<1));
44 }
45 int main()
46 {
47     scanf("%lld%lld",&n,&m);
48     for (ll i=2,x,y;i<=n;i++) scanf("%lld%lld",&x,&y),insert(x,y);
49     for (ll i=1;i<=n;i++) scanf("%lld",&c[i]),w[i]=c[i];
50     dfs1(1),dfs2(1,1);
51     for (ll op,x,y;m;m--)
52     {
53         scanf("%lld%lld",&op,&x);
54         if (op==1) scanf("%lld",&y),y-=c[x],c[x]+=y,modify(x,y); else printf("%lld\n",calc(x));
55     }
56 }

 

标签:pre,剖分,Luogu,ll,P3676,id,add,son,top
来源: https://www.cnblogs.com/Comfortable/p/11329275.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有