【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 ...
随机推荐
- 一个经典的PHP加密解密算法authcode
项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理.最常见的应用在用户登录以及一些API ...
- 强化学习读书笔记 - 09 - on-policy预测的近似方法
强化学习读书笔记 - 09 - on-policy预测的近似方法 参照 Reinforcement Learning: An Introduction, Richard S. Sutton and A ...
- Zigbee系列(概览)
Zigbee技术特点 低速率: 数据传输速率只有20~250kb/s, 2.4GHZ提供250kb/s, 915MHz对应40kb/s, 868Mhz对应20kb/s 低功耗:睡眠模式设备使用电池供电 ...
- 8 个用于业余项目的优秀 Python 库
在 Python/Django 的世界里有这样一个谚语:为语言而来,为社区而留.对绝大多数人来说的确是这样的,但是,还有一件事情使得我们一直停留在 Python 的世界里,不愿离开,那就是我们可以很容 ...
- 做程序开发的你如果经常用Redis,这些问题肯定会遇到
分布式缓存Redis是一种支持Key-Value等多种数据结构的存储系统.可用于缓存.事件发布或订阅.高速队列等多种场景.Redis使用ANSI C语言编写,提供字符串(String).哈希(Hash ...
- 首次使用windows管理界面访问安装在UNIX或linux下的DP服务器时提示无权限访问的解决方法
用windwos GUI管理界面连接时提示无权限访问: 在/etc/opt/omni/server/users/userlist 添加一行: "" "*" &q ...
- Debian 给非 ROOT 用户添加 sudoer 权限
问题描述 从官方镜像安装的 Debian 9 (Stretch)比较纯净,但因此需要自己安装.配置许多常用的 Linux 应用,这里就需要 sudo (super user do)临时获取 root ...
- 洛谷【P1052】过河
https://www.luogu.org/problemnew/show/P1052 题目描述 在河上有一座长度为 L 的独木桥, 一只青蛙想沿着独木桥从河的一侧跳到另一侧. 在桥上有一些石子, 青 ...
- C语言—单链表
单链表操作:读取,插入和删除 #include "stdafx.h" #include <string.h> #include <stdio.h> #inc ...
- ShipStation Now Uses AWS And Amazon Fulfillment To Automatically Ship From eBay, Sears And Other Marketplaces
ShipStation today unveiled a first-of-its-kind service to leverage Amazon Web Services and Amazon.co ...