luogu 3676小清新数据结构题
真·小清新...
其实本题正解是动态点分治,但是考虑到那个东西需要先大力推导一波再套上一个幻想乡战略游戏的搞法,所以还不如大力推导一波,然后无脑套上一个树剖+线段树写法...
首先我们考虑没有换根操作:
没有换根操作时,设每次修改的变化量为$\delta$,很显然每次修改时只会影响一条树链上的贡献,设$s_{i}$表示以$i$为根节点的子树权值和,那么每次修改对答案产生的贡献是:
$\sum_{i\in [p~root]}(s_{i}+\delta)^{2}-\sum_{i\in [p~root]}s_{i}^{2}$
展开这个表达式,得:
$dep_{p}\delta^{2}+2\delta\sum_{i\in [p~root]}s_{i}$
也就是说,我们实际维护的是$s_{i}$,每次修改只需给答案加上那个表达式即可
而维护$s_{i}$可以简单地树剖+线段树区间修改,区间查询算得
那么考虑下一个问题:
如果换根怎么办?
我们考虑换根之后对答案的影响:
显然要点仍然在从这个节点到根的路径上:
我们设路径上的每个点为$p_{1},p_{2},...p_{dep}$(按顺序)
设对于点$p_{i}$,在以$1$为根时子树点权和为$s_{i}$,在以$p$为根时点权和为$s^{'}_{i}$
那么我们考虑:对任意一个$i$,都满足:$s_{i}+s^{'}_{i+1}=s_{1}=s^{'}_{dep}$
也就是整棵树的点权和等于一个节点上半部分点权和+下半部分点权和
于是我们来推导一下现在的答案:
设以$1$为根的答案为$ans_{1}$
那么$ans=ans_{1}-\sum_{i=1}^{dep}s_{i}^{2}+\sum_{i=1}^{dep}(s^{'}_{i})^{2}$
借助上面的表达式,得到:
$ans=ans_{1}-\sum_{i=1}{dep}s_{i}^{2}+\sum_{i=1}^{dep-1}(s_{1}-s_{i+1})^{2}+(s^{'}_{dep})^{2}$
那么也就是:
$ans=ans_{1}-\sum_{i=1}^{dep}s_{i}^{2}+deps_{1}^{2}-2s_{1}\sum_{i=2}^{dep}s_{i}+\sum_{i=2}^{dep}s_{i}^{2}$
于是:
$ans=ans_{1}+(dep-1)s_{1}^{2}-2s_{1}\sum_{i=1}^{dep}s_{i}+2s_{1}$
整理一下:
$ans=ans_{1}+s_{1}[(dep+1)s_{1}-2\sum_{i=1}^{dep}s_{i}]$
因此我们仍然只需维护$s_{i}$即可
这样树剖+线段树就可以完美解决这个问题了
贴代码:
// luogu-judger-enable-o2
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define rt1 rt<<1
#define rt2 (rt<<1)|1
#define ll long long
using namespace std;
struct Edge
{
int nxt,to;
}edge[400005];
struct Seg_tree
{
ll lazy,sum;
}tree[800005];
int head[200005];
int cnt=1;
int siz[200005],son[200005],nnum[200005],onum[200005],ttop[200005],dep[200005],f[200005];
ll w[200005],s[200005];
int tot;
ll ans=0;
int n,m;
void add(int l,int r)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
void dfs(int x,int fx)
{
siz[x]=1,f[x]=fx,dep[x]=dep[fx]+1,s[x]=w[x];
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
dfs(to,x);
siz[x]+=siz[to],s[x]+=s[to],son[x]=siz[son[x]]<siz[to]?to:son[x];
}
ans+=s[x]*s[x];
}
void redfs(int x,int topx,int fx)
{
ttop[x]=topx,nnum[x]=++tot,onum[tot]=x;
if(son[x])redfs(son[x],topx,x);
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx||to==son[x])continue;
redfs(to,to,x);
}
}
void buildtree(int rt,int l,int r)
{
if(l==r){tree[rt].sum=s[onum[l]];return;}
int mid=(l+r)>>1;
buildtree(rt1,l,mid),buildtree(rt2,mid+1,r);
tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
void pushdown(int rt,int l,int r)
{
tree[rt1].lazy+=tree[rt].lazy,tree[rt2].lazy+=tree[rt].lazy;
int mid=(l+r)>>1;
tree[rt1].sum+=(mid-l+1)*tree[rt].lazy,tree[rt2].sum+=(r-mid)*tree[rt].lazy;
tree[rt].lazy=0;
}
void update(int rt,int l,int r,int lq,int rq,ll v)
{
if(l>=lq&&r<=rq)
{
tree[rt].lazy+=v,tree[rt].sum+=(r-l+1)*v;
return;
}
if(tree[rt].lazy)pushdown(rt,l,r);
int mid=(l+r)>>1;
if(lq<=mid)update(rt1,l,mid,lq,rq,v);
if(rq>mid)update(rt2,mid+1,r,lq,rq,v);
tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
ll query(int rt,int l,int r,int lq,int rq)
{
if(l>=lq&&r<=rq)return tree[rt].sum;
int mid=(l+r)>>1;
if(tree[rt].lazy)pushdown(rt,l,r);
ll ret=0;
if(lq<=mid)ret+=query(rt1,l,mid,lq,rq);
if(rq>mid)ret+=query(rt2,mid+1,r,lq,rq);
return ret;
}
void pushup(int x,ll v)
{
while(x){update(1,1,n,nnum[ttop[x]],nnum[x],v),x=f[ttop[x]];}
}
ll l_query(int x)
{
ll ret=0;
while(x){ret+=query(1,1,n,nnum[ttop[x]],nnum[x]),x=f[ttop[x]];}
return ret;
}
template <typename T>inline void read(T &x)
{
T f=1,c=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
x=c*f;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
for(int i=1;i<=n;i++)read(w[i]);
dfs(1,0),redfs(1,1,1);
buildtree(1,1,n);
while(m--)
{
int typ;
read(typ);
if(typ==1)
{
int x;
ll v;
read(x),read(v);
ans+=(v-w[x])*(v-w[x])*dep[x];
ans+=2*(v-w[x])*l_query(x);
pushup(x,v-w[x]);
w[x]=v;
}else
{
int x;
read(x);
ll temp1=query(1,1,n,nnum[1],nnum[1]);
ll temp2=l_query(x);
ll temps=temp1*((dep[x]+1)*temp1-2*temp2);
printf("%lld\n",ans+temps);
}
}
return 0;
}
luogu 3676小清新数据结构题的更多相关文章
- Luogu 3676 小清新数据结构题
推荐博客: http://www.cnblogs.com/Mychael/p/9257242.html 感觉还挺好玩的 首先考虑以1为根,把每一个点子树的权值和都算出来,记为$val_{i}$,那么在 ...
- 【Luogu3676】小清新数据结构题(动态点分治)
[Luogu3676]小清新数据结构题(动态点分治) 题面 洛谷 题解 先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护. 做法大概是这样: 我们先以任意一个点为根,把当前点看成是一棵有根 ...
- 洛谷 P3676 小清新数据结构题
https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...
- [Luogu3676]小清新数据结构题
题面戳我 题意:给一棵树,树上有点权,每次操作为修改一个点的点权,或者是询问以某个点为根时,每棵子树(以每个点为根,就有n棵子树)点权和的平方和. \(n\le2*10^5\),保证答案在long l ...
- [P3676]小清新数据结构题
Description: 给你一棵树,每次询问以一个点为根时所有子树点权和的平方和 带修改 Hint: \(n\le 2*10^5\) Solution: 这题只要推出式子就很简单了 如果不换根这个平 ...
- Luogu3676 小清新数据结构题 动态点分治
传送门 换根类型的统计问题动态点分治都是很好做的. 设所有点的点权和为$sum$ 首先,我们先不考虑求$\sum\limits_i s_i^2$,先考虑如何在换根的情况下求$\sum\limits_i ...
- 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)
传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...
- [luogu3676] 小清新数据结构题 [树链剖分+线段树]
题面 传送门 思路 本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的 所以只能另辟蹊径 首先,我们考虑询问点都在1的 ...
- 洛谷 P3676 - 小清新数据结构题(动态点分治)
洛谷题面传送门 题目名称好评(实在是太清新了呢) 首先考虑探究这个"换根操作"有什么性质.我们考虑在换根前后虽然每个点的子树会变,但整棵树的形态不会边,换句话说,割掉每条边后,得到 ...
- 洛谷P3676 小清新数据结构题 [动态点分治]
传送门 思路 这思路好妙啊! 首先很多人都会想到推式子之后树链剖分+线段树,但这样不够优美,不喜欢. 脑洞大开想到这样一个式子: \[ \sum_{x} sum_x(All-sum_x) \] 其中\ ...
随机推荐
- win10如何设置共享媒体流?
一.win10设置媒体流共享 1 电脑开机后,点击右下角的"网络连接-网络和Internet设置". 2 进入设置界面后,点击"网络和共享中心". ...
- 小白之Python-基础中的基础05
Python-基础中的基础05 --之元组 #元组:不可变更1. 创建元组:元组必须用,表示,只加()是不行的 print 42 print (42) print 43, #这个地方会把下一行的内容打 ...
- IO学习笔记7
2.4 多路复用javaAPI 在上面我们简单java代码实现了多路复用,是一个单线程版的.讲上面的epoll代码复制到linux服务器中,使用strace追踪系统调用. javaAPI会根据系统类型 ...
- 推荐优秀国产蓝牙芯片-HS6621CxC系列
HS6621CxC是一个优化功耗真正芯片系统(SOC)解决方案,适用于蓝牙低功耗和私有的2.4GHz应用场景.它集成了一个高性能.小功率的射频收发器,具有蓝牙基带和丰富的外围IO扩展. HS6621C ...
- django中读取settings中的相关参数
from django.conf import settings print(settings.IP_LOCAL)
- 阻塞I/O,非阻塞I/O,同步I/O,异步I/O
根据应用程序是否阻塞自身运行分为: 阻塞I/O:是指应用程序在执行I/O操作后,如果没有获得响应, 就会阻塞当前线程,不能执行其他任务. 非阻塞I/O:是指应用程序在执行I/O操作后 ...
- SQL server数据库 账户SA登录失败,提示错误:18456
在我们使用数据库的时候,偶尔会遇到一些登录上的错误提示.比如,在数据库配置上没有正确开启用户的登录策略以及服务器身份验证模式时,就会提示"用户'sa'登录失败.(Microsoft SQL ...
- MCU构成及其运行原理
MCU构成及其运行原理 1. MCU概念 MCU,微控制单元(Microcontroller Unit) ,又称单片微型计算机(Single Chip Microcomputer )或者单片机,是把中 ...
- 提交docker镜像到远程仓库
生成镜像 Docker build 镜像 编辑Dockerfile文件 新建Dockerfile文件,将如下构建脚本复制进去 # Build for ansible envirament FROM c ...
- vscode vue代码模板
{ "Print to console": { "prefix": "vue", "body": [ "< ...