【Luogu3676】小清新数据结构题(动态点分治)
【Luogu3676】小清新数据结构题(动态点分治)
题面
题解
先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护。
做法大概是这样:
我们先以任意一个点为根,把当前点看成是一棵有根树。比方说以\(1\)为根。
那么,在询问以\(p\)为根的时候的答案,我们看看哪些子树发生了变化。
发现真正会产生变化的只有\(1..p\)这条链上的所有点,其它点的贡献和以\(1\)为根时的贡献是一样的。
考虑这条链上的所有点的贡献变成了什么,假设这条链上的所有点分别是\(c_1,c_2...,c_n\)
那么\(c_i\)的子树和是\(\sum Val-\sum _{SubTree c_{i+1}}Val\),
也就是整棵树的所有权值和减去这条链上的那个儿子的子树和。
因为最终的贡献有个平方,所以我们维护子树的\((\sum Val)^2\),\(\sum Val\),
修改的时候把平方式拆开来维护就好了
更丧一点,你可以把\([(\sum val)^2,\sum val , c]\)看成一个矩阵,每次修改相当于一个矩阵乘法
其中\(c=1\)。
这样子就可以用线段树+树链剖分来维护了。
这样应该是对的吧,我没有实践,纯属yy
以上内容都是废话,可以当做没有看见
还是一样,先确定为一棵有根树,
设\(s_i\)表示以\(i\)为根的的子树的权值和,\(w\)为整棵树的权值和。
我们要求的东西是\(\sum_{i=1}^n s_i^2\)
发现\(\sum_{i=1}^n s_i(w-s_i)\)是定值。
证明是这样的,我们考虑一下上述式子是个什么东西,即在任意一个点的子树内和子树外中选择一个点然后求他们的乘积和。
那么,对于任意一对\((u,v)\),他们产生的贡献的次数显然是枚举路径上除了\(lca\)外的任意一个点进行选择,那么路径上的点数是定值,所以上述式子是定值。
那么这就很好办了,\(w\)是很容易维护的,所以我们只需要维护出\(\sum_{i=1}^ns_i\)
就有\(\sum_{i=1}^ns_i^2=w\sum_{i=1}^ns_i-P\),其中\(P\)就是这个定值。
这样子以来,所有的东西都可以利用动态点分治维护即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 222222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,m,V[MAX];
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
/********************************************************************/
int size[MAX],dfn[MAX],top[MAX],dep[MAX],fa[MAX],tim,hson[MAX];
void dfs1(int u,int ff)
{
fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
dfs1(v,u);size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(hson[u])dfs2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=fa[u]&&e[i].v!=hson[u])
dfs2(e[i].v,e[i].v);
}
int LCA(int u,int v)
{
while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
return dep[u]<dep[v]?u:v;
}
int Dis(int u,int v){return dep[u]+dep[v]-2*dep[LCA(u,v)];}
/********************************************************************/
bool vis[MAX];
int Fa[MAX],Size,root,mx;
void Getroot(int u,int ff)
{
size[u]=1;int ret=0;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff||vis[v])continue;
Getroot(v,u);size[u]+=size[v];
ret=max(ret,size[v]);
}
ret=max(ret,Size-size[u]);
if(ret<mx)mx=ret,root=u;
}
void DFS(int u,int ff)
{
vis[u]=true;Fa[u]=ff;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(vis[v])continue;
mx=Size=size[v];
Getroot(v,u);DFS(root,u);
}
}
/********************************************************************/
ll P,W;
ll sum[MAX],tf[MAX],num[MAX];
void Modify(int u,int w)
{
num[u]+=w;
for(int i=u;Fa[i];i=Fa[i])
{
int d=Dis(u,Fa[i]);
num[Fa[i]]+=w;sum[Fa[i]]+=1ll*w*d;
tf[i]+=1ll*w*d;
}
}
ll Query(int u)
{
ll ret=sum[u];
for(int i=u;Fa[i];i=Fa[i])
{
int d=Dis(u,Fa[i]);
ret+=1ll*d*(num[Fa[i]]-num[i]);
ret+=sum[Fa[i]]-tf[i];
}
return ret;
}
void dfs(int u,int ff)
{
size[u]=V[u];
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)dfs(e[i].v,u),size[u]+=size[e[i].v];
P+=1ll*size[u]*(W-size[u]);
}
/********************************************************************/
int main()
{
n=read();m=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read();
Add(u,v);Add(v,u);
}
for(int i=1;i<=n;++i)V[i]=read();
dfs1(1,0);dfs2(1,1);
Size=mx=n;Getroot(1,0);DFS(root,0);
for(int i=1;i<=n;++i)Modify(i,V[i]),W+=V[i];
dfs(1,0);
while(m--)
{
int opt=read(),x=read(),y;
if(opt==1)
{
y=read();Modify(x,y-V[x]);W+=y-V[x];
P+=(y-V[x])*Query(x);V[x]=y;
}
else printf("%lld\n",(Query(x)+W)*W-P);
}
return 0;
}
【Luogu3676】小清新数据结构题(动态点分治)的更多相关文章
- Luogu3676 小清新数据结构题 动态点分治
传送门 换根类型的统计问题动态点分治都是很好做的. 设所有点的点权和为$sum$ 首先,我们先不考虑求$\sum\limits_i s_i^2$,先考虑如何在换根的情况下求$\sum\limits_i ...
- 洛谷P3676 小清新数据结构题 [动态点分治]
传送门 思路 这思路好妙啊! 首先很多人都会想到推式子之后树链剖分+线段树,但这样不够优美,不喜欢. 脑洞大开想到这样一个式子: \[ \sum_{x} sum_x(All-sum_x) \] 其中\ ...
- [Luogu3676]小清新数据结构题
题面戳我 题意:给一棵树,树上有点权,每次操作为修改一个点的点权,或者是询问以某个点为根时,每棵子树(以每个点为根,就有n棵子树)点权和的平方和. \(n\le2*10^5\),保证答案在long l ...
- [luogu3676] 小清新数据结构题 [树链剖分+线段树]
题面 传送门 思路 本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的 所以只能另辟蹊径 首先,我们考虑询问点都在1的 ...
- Luogu3676 小清新数据结构题(树链剖分+线段树)
先不考虑换根.考虑修改某个点权值对答案的影响.显然这只会改变其祖先的子树权值和,设某祖先原子树权值和为s,修改后权值增加了x,则对答案的影响为(s+x)2-s2=2sx+x2.可以发现只要维护每个点到 ...
- 洛谷 P3676 - 小清新数据结构题(动态点分治)
洛谷题面传送门 题目名称好评(实在是太清新了呢) 首先考虑探究这个"换根操作"有什么性质.我们考虑在换根前后虽然每个点的子树会变,但整棵树的形态不会边,换句话说,割掉每条边后,得到 ...
- 【刷题】洛谷 P3676 小清新数据结构题
题目背景 本题时限2s,内存限制256M 题目描述 在很久很久以前,有一棵n个点的树,每个点有一个点权. 现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方 ...
- 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)
传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...
- 洛谷 P3676 小清新数据结构题
https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...
随机推荐
- java class file
目录 什么是java类文件 幻数 主次版本号 常量池数和常量池 this_class super_class 接口数量和接口 字段数和字段 方法数和方法 以下内容主要还是参考<Inside JV ...
- APP端测试,常见功能测试点汇总
除去每个产品和版本不同的业务需求以及功能,针对于大多数的APP的共同点和移动设备的特性,本文总结了一些APP功能测试中经常遇见,需要考虑到的测试点以共参考 一.安装和卸载 应用的安装和卸载在任何一款A ...
- GitHub 多人协作开发 三种方式:
GitHub 多人协作开发 三种方式: 一.Fork 方式 网上介绍比较多的方式(比较大型的开源项目,比如cocos2d-x) 开发者 fork 自己生成一个独立的分支,跟主分支完全独立,pull代码 ...
- webpack整体配置结构
摘自<深入浅出webpack>2.8 const path = require('path'); module.exports = { // entry 表示入口,webpack执行的第一 ...
- 最大公共子串:DP
标题:最大公共子串 最大公共子串长度问题就是:求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc",可以找 ...
- 无法找到 ContextLoaderListener 类
问题:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener 原因:Eclips ...
- react native组件的生命周期
react native组件的生命周期 一.当页面第一次加载时,会依次调用: constructor() componentWillMount(): 这个函数调用时机是在组件创建,并初始化了状态之后, ...
- php异步学习(1)
1.为啥PHP需要异步操作? 一般来说PHP适用的场合是web页面展示等耗时比较短的任务,如果对于比较花时间的操作如resize图片.大数据导入.批量发送EDM.SMS等,就很容易出现操作超时情况.你 ...
- BETA阶段冲刺
1.介绍小组新加入的成员,Ta担任的角色 新成员 担任工作 江鹭涛 前端设计 2.讨论是否需要更换团队的PM 不需要,上阶段配合不错,这阶段继续努力 3.下一阶段需要改进完善的功能 服务器并发处理,界 ...
- C++对象内存布局测试总结
C++对象内存布局测试总结 http://hi.baidu.com/����/blog/item/826d38ff13c32e3a5d6008e8.html 上文是半年前对虚函数.虚拟继承的理解.可能 ...