传送门

Description

有一棵\(n\)个点的树,每个点有一个点权。

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

Solution

我们设\(Sum=\sum_{i=1}^{n} w_i\),\(s_i\)表示\(i\)子树的权值和

发现不管根是哪个节点,\(W=\sum_{i=1}^n s_i(Sum-s_i)\)都是一个定值

因为它相当于对于每条边连接的两个联通块的”点权和的积“的和

所以,我们要求的\(\sum_{i=1}^{n} s_i^2=Sum*(\sum_{i=1}^n s_i)-W\)

考虑怎么计算\(calc(root)=\sum_{i=1}^{n} s_i\)

发现其实上就是\(Sum+\sum_{i=1}^n dis(root,i)*val_i\)

可以用点分树来维护

考虑怎么计算\(W\)

对于每次修改\(val_i+=delta\),就有\(W+=\sum_{j=1}^n val_j*dis(i,j)*delta=delta*calc(i)\)

发现这道题本质和幻想乡战略游戏是一样的

可是把原来的代码交上去,就\(TLE\)了,只好考虑重构

不妨把过程重新理一遍:

  1. 点分树有一个性质,对于树上的两个点,它们的\(lca\)一定在两点在原树上的简单路径上

    因此,要求两个点的实际距离,可以通过分别计算它们到\(lca\)的实际距离求和得到

  2. 考虑以上性质,我们可以设:

    • \(vsum_i\)表示\(i\)在点分树上的子树内的权值和
    • \(dis1_i\)表示 \(\sum_{j} dis(i,j)*val_j\),\(j\)是\(i\)在点分树上的子树内的节点
    • \(dis2_i\)表示 \(\sum_{j} dis(par_i,j)*val_j\)
    • \(par_i\)是\(i\)在点分树上的父亲
  3. \(dis1_i=\sum_{son} dis2_son\),\(son\)是\(i\)在点分树上的儿子

  4. \(calc(i)\)其实上就是枚举\(lca\)

    \(lca=i\)时,和为\(dis1_i\)

    \((\sum_{lca=par_j} dis1_{par_j}-dis2_j)\)算的是外围节点到\(lca\)的和

    \(dis(i,par_j)*(vsum_{par_j}-vsum_j))\)算的是它们到\(i\)的和

我们发现,求距离的部分其实不需要像之前那样全部记下来,可以用\(RMQ\)求树上距离

具体来说,和\(RMQ\)求\(LCA\)差不多,只不过维护的最小值不是欧拉序,而是到根路径的长

Code

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define reg register
#define int llinline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*f;
}
const int MN=2e5+5;int n,m;
struct edge{int to,w,nex;}e[MN<<2];int en,hr[MN];
void ins(int x,int y,int w,int *h){e[++en]=(edge){y,w,h[x]};h[x]=en;}
int Val[MN],O,SUM;struct Tree
{int Hr[MN],ind,st[MN<<2][21],dep[MN],pos[MN<<1],lg[MN<<2],_siz[MN];inline void Ins(int x,int y,int w){ins(x,y,w,Hr);ins(y,x,w,Hr);}int dis(int x,int y){if(pos[x]>pos[y]) std::swap(x,y);reg int k=lg[pos[y]-pos[x]+1];return dep[x]+dep[y]-2*min(st[pos[x]][k],st[pos[y]-(1<<k)+1][k]);}void dfs(int x,int fa=0){st[pos[x]=++ind][0]=dep[x];reg int i;for(i=Hr[x];i;i=e[i].nex)if(e[i].to^fa)dep[e[i].to]=dep[x]+e[i].w,dfs(e[i].to,x),st[++ind][0]=dep[x];}void get_O(int x=1,int fa=0){reg int i;_siz[x]=Val[x];for(i=Hr[x];i;i=e[i].nex)if(e[i].to^fa)get_O(e[i].to,x),_siz[x]+=_siz[e[i].to];O+=1ll*(SUM-_siz[x])*_siz[x];}inline void pre_work(){reg int i,j;get_O();dfs(1);for(lg[0]=-1,i=1;i<(MN<<2);i++)lg[i]=lg[i>>1]+1;for(j=1;j<20;++j)for(i=1;i+(1<<j)-1<=ind&&i<=ind;++i)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);}}T;int sum,rt,mx[MN],vis[MN],par[MN],cnt,siz[MN];
ll dis1[MN],dis2[MN],sumv[MN];void getrt(int x,int fa)
{siz[x]=1;mx[x]=0;reg int i;for(i=T.Hr[x];i;i=e[i].nex)if(!vis[e[i].to]&&(e[i].to!=fa))getrt(e[i].to,x),siz[x]+=siz[e[i].to],mx[x]=max(mx[x],siz[e[i].to]);mx[x]=max(mx[x],sum-siz[x]);if(mx[x]<mx[rt]) rt=x;
}void _work(int x,int fa)
{vis[x]=1;par[x]=fa;reg int i;for(i=T.Hr[x];i;i=e[i].nex)if(!vis[e[i].to])mx[rt=0]=sum=siz[e[i].to],getrt(e[i].to,0),ins(x,rt,0,hr),_work(rt,x);
}void pre_work()
{sum=mx[rt=0]=n;getrt(1,0);int tmp=rt;_work(rt,0);rt=tmp;
}inline void Modify(int x,int val)
{sumv[x]+=val;reg int i,dis;for(i=x;par[i];i=par[i]){dis=T.dis(par[i],x);dis1[par[i]]+=dis*val;dis2[i]+=dis*val;sumv[par[i]]+=val;}
}inline ll calc(int x)
{ll ans=dis1[x];reg int i,dis;for(i=x;par[i];i=par[i]){dis=T.dis(par[i],x);ans+=dis1[par[i]]-dis2[i];ans+=dis*(sumv[par[i]]-sumv[i]);}return ans;
}signed main()
{n=read();m=read();reg int i,x,y;for(i=1;i<n;i++) x=read(),y=read(),T.Ins(x,y,1);pre_work();for(i=1;i<=n;++i) SUM+=Val[i]=read();T.pre_work();for(i=1;i<=n;++i) Modify(i,Val[i]);while(m--){reg int opt=read();if(opt==1){x=read();y=read()-Val[x];Modify(x,y);SUM+=y;O+=y*calc(x);Val[x]+=y;}else printf("%lld\n",SUM*(calc(read())+SUM)-O);}return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

转载于:https://www.cnblogs.com/PaperCloud/p/10664448.html

lp3676 小清新数据结构题相关推荐

  1. [luogu3676]小清新数据结构题

    前言 此题貌似有不少做法 题目相关 链接 题目大意 给出一棵无根树,支持两个操作 1.修改一个点的权值 2.指定一个点,计算以其为根时每个子树权值平方和 数据范围 n,q≤200000n,q\le20 ...

  2. 洛谷P3676 小清新数据结构题(动态点分治)

    题面在这里>>> 解题思路: 开始写了个LCT后来发现是错的QAQ 正解是动态点分治. 对于一个点,其答案就是$\sum_{i=1}^{n}sum_{i}^{2}$ 很神奇地构造出这 ...

  3. 洛谷3672:小清新签到题——题解

    https://www.luogu.org/problemnew/show/P3672 题目见上面. 参考:https://www.cnblogs.com/candy99/p/6582699.html ...

  4. 怎么获取codeforces的数据_原创 | codeforces 1417C,逆向思考的数据结构题

    点击上方蓝字,关注并星标,和我一起学技术. 大家好,欢迎阅读周末算法题专题. 今天我们选择的是codeforces contest 1417的C题k-Amazing Numbers.这是一道经典的数据 ...

  5. 花神游历各国 题解(小清新线段树/树状数组+并查集)

    题面 众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于 ...

  6. 【python】一道LeetCode搞懂递归算法!#131分割回文串 #以及刷LeetCode的一点点小心得 [数据结构与算法基础]

    题目:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串.返回 s 所有可能的分割方案. # 示例 输入: "aab" 输出: [["aa",&q ...

  7. OSChina 周三乱弹 ——技校重金属跟小清新画风的妹子

    2019独角兽企业重金招聘Python工程师标准>>> @子匠_Zijor:卷珠帘,有古时味道的歌.不是一般的幽怨. 卷珠帘 - 霍尊 手机党少年们想听歌,请使劲儿戳(这里) 夜月明 ...

  8. 小清新人渣的本愿(莫队+bitset)

    小清新人渣的本愿 这两天写了些 b i t s e t bitset bitset的题,但都不想写题解...正巧这道题还结合了莫队,也是正在学习的,就记录一下吧. 题意: 给定一个 a a a数组,有 ...

  9. c语言数据结构算法设计题,数据结构题集(C语言版)算法设计题答案[].doc

    数据结构题集(C语言版)算法设计题答案[].doc 第一章 绪论 1.16 void print_descending(int x,int y,int z)// 按从大到小顺序输出三个数 { scan ...

最新文章

  1. 总结 20 个开发细节
  2. 树转化为二叉树_森林转化为二叉树(详解版)
  3. 虚函数和作用域(C++ primer 第五版)P550
  4. Minikube-运行在笔记本上的Kubernetes集群
  5. 【elasticsearch】 document 查询原理
  6. mysql 计划任务关闭_mysql计划任务
  7. Spring 注解 @Controller,@Service,@Repository,@Component,重定向 与 服务端跳转
  8. gfsk调制频谱_gfsk调制方式
  9. OD查找QQ sessionkey教程
  10. 信源编码的三种方式与实现
  11. 阿里云服务器出网带宽和入网带宽是什么意思,5M宽带怎么计算?
  12. Blender-绑定动画Auto-Rig Pro 重映射动捕FBX 小K结合 的问题以及解决
  13. 星号下三角形python答案_Python利用for循环打印星号三角形的案例
  14. chrome android版 插件下载,Chrome安卓下载
  15. MySql数据库中的权限授予
  16. 计算机网络基础(类别 | 性能指标 | OSI模型初识)
  17. ESP8266接入阿里云物联网平台上传温湿度数据
  18. Linux服务器配置 PC NVR
  19. cityengine快速创建城市模型
  20. 【B站弹幕游戏开发笔记01】Win10系统下给Unity项目导入Protobuf

热门文章

  1. html5晋级之路-css背景
  2. 配置汇编环境:使用vs2010+MASM
  3. python3 random模块操作
  4. mysql如何给表字段加密_Mysql 字段加密
  5. c++ auto用法_不想写表达式的类型?试试auto吧
  6. 如何安装php5.5,源码安装php5.5
  7. 小明一家过桥_【练习】用python解决小明一家过桥问题
  8. termux php 出错,android上的终端——termux
  9. java word在线预览_java 生成word文档并且在线预览的问题
  10. less简介、less安装、编译、less语法之变量、嵌套、类混入、函数混入、运算、less文件导入