洛谷P3676 小清新数据结构题(动态点分治+树链剖分)
感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~
先膜一波zsy大佬
讲讲做法。题目的要求是给定一个根$p$,求$\sum _{i=1}^ns_i^2$,其中$s_i$表示子树中的点权和
我们设$sum=\sum _{i=1}^n val_i$,即整棵树的点权和。先考虑一下$\sum _{i=1}^ns_i$怎么求。考虑一下每一个点的贡献,每一个点都会对被计算$dep_i+1$次(其中$dep_i$表示$dist(i,p)$),那么很显然$\sum _{i=1}^ns_i=\sum_{i=1}^nval_i*(dep_i+1)=\sum_{i=1}^nval_i*dep_i+sum$。然后考虑一下$val_i*dep_i$,如何动态维护?->幻想乡战略游戏……
简单来说,就是建好点分树,然后每一次及时修改和查询
然后我们令$calc(p)$以$p$为根时的$\sum _{i=1}^nval_i*dep_i$
然后考虑如下式子$$\sum_{i=1}^n\sum_{j=1}^nval_i*val_j*dist(i,j)$$
是不是可以理解为在所有的点对$(i,j)$之间的所有边上加上权值$val_i*val_j$(刚好有$dist(i,j)$条边),然后再求整棵树的权值?
然后我们考虑一下每条边的权值,肯定等于两侧的子树点权和的乘积。那么,不论是以哪一个点$p$为根,它的权值都等于$s_i*(sum-s_i)$,其中$s_i$表示这条边指向的儿子的子树的点权和
那么,上面的式子就可以变成这样$$\sum_{i=1}^n\sum_{j=1}^nval_i*val_j*dist(i,j)=\sum_{i=1}^ns_i*(sum-s_i)$$
又因为上式左边是不变的,所以不管选取哪一个$p$为根,右边都是不变的
令$W=\sum_{i=1}^ns_i*(sum-s_i)$,然后可以直接$O(n)dp$出$W$,然后考虑对点的修改对$W$造成的影响
$W=\sum_{i=1}^n\sum{j=1}^nval_i*val_j*dist(i,j)$,设点$u$的变化量为$Δv$,那么$ΔW=Δv*\sum_{j=1}^nval_j*dist(i,j)$,相当于$Δv*calc(i)$,然后可以考虑和一般的动态点分一样计算
然后最后询问的答案就是$$W=\sum_{i=1}^ns_i*(sum-s_i)$$
$$\sum_{i=1}^ns_i^2=\sum_{i=1}^ns_i*sum-W$$
$$\sum_{i=1}^ns_i^2=sum(calc(i)+sum)-W$$
// luogu-judger-enable-o2
//minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(ll x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=;
int ver[N<<],head[N],Next[N<<];
int val[N],fa[N],pa[N],d[N],sz[N],son[N],top[N];
int n,q,tot;
void dfs1(int u,int fa){
pa[u]=fa,d[u]=d[fa]+,sz[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];if(v==fa) continue;
dfs1(v,u);
sz[u]+=sz[v];if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int fa){
top[u]=fa;
if(son[u]) dfs2(son[u],fa);else return;
for(int i=head[u];i;i=Next[i])
if(ver[i]!=pa[u]&&ver[i]!=son[u])
dfs2(ver[i],ver[i]);
}
int LCA(int u,int v){
while(top[u]^top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
u=pa[top[u]];
}
return d[u]<d[v]?u:v;
}
int dis(int u,int v){return d[u]+d[v]-(d[LCA(u,v)]<<);}
int size,rt,vis[N];
ll sum[N],sum1[N],sum2[N],sigma,omega,ans;
void getrt(int u,int fa){
sz[u]=,son[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];if(v==fa||vis[v]) continue;
getrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
}
cmax(son[u],size-sz[u]);
if(son[u]<son[rt]) rt=u;
}
void solve(int u,int f){
fa[u]=f,vis[u]=;int totsz=size;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(!vis[v]){
size=sz[v]>sz[rt]?totsz-sz[rt]:sz[v];
rt=;
getrt(v,),solve(rt,u);
}
}
}
inline void modify(int u,int v){
sum[u]+=v;
for(int i=u;fa[i];i=fa[i]){
int dist=dis(u,fa[i]);
sum[fa[i]]+=v;
sum1[fa[i]]+=dist*v;
sum2[i]+=dist*v;
}
}
inline ll calc(int u){
ll res=sum1[u];
for(int i=u;fa[i];i=fa[i]){
int dist=dis(fa[i],u);
res+=(ll)dist*(sum[fa[i]]-sum[i]);
res+=sum1[fa[i]]-sum2[i];
}
return res;
}
void DP(int u,int fa){
sz[u]=val[u];
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa) DP(v,u),sz[u]+=sz[v];
}
omega+=1ll*sz[u]*(sigma-sz[u]);
}
int main(){
n=read(),q=read();
for(int i=;i<n;++i){
int u=read(),v=read();
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
dfs1(,),dfs2(,);
size=n,son[rt=]=n+;
getrt(,),solve(rt,);
for(int i=;i<=n;++i)
val[i]=read(),modify(i,val[i]),sigma+=val[i];
DP(,);
while(q--){
int opt=read(),x=read();
if(opt&){
int y=read();y-=val[x];
modify(x,y),sigma+=y,omega+=y*calc(x);
val[x]+=y;
}
else print((calc(x)+sigma)*sigma-omega);
}
Ot();
return ;
}
洛谷P3676 小清新数据结构题(动态点分治+树链剖分)的更多相关文章
- 洛谷P3676 小清新数据结构题 [动态点分治]
传送门 思路 这思路好妙啊! 首先很多人都会想到推式子之后树链剖分+线段树,但这样不够优美,不喜欢. 脑洞大开想到这样一个式子: \[ \sum_{x} sum_x(All-sum_x) \] 其中\ ...
- 洛谷P3676 小清新数据结构题 【树剖 + BIT】
题目链接 洛谷P3676 题解 我们先维护\(1\)为根的答案,再考虑换根 一开始的答案可以\(O(n)\)计算出来 考虑修改,记\(s[u]\)表示\(u\)为根的子树的权值和 当\(u\)节点产生 ...
- 洛谷 P3676 - 小清新数据结构题(动态点分治)
洛谷题面传送门 题目名称好评(实在是太清新了呢) 首先考虑探究这个"换根操作"有什么性质.我们考虑在换根前后虽然每个点的子树会变,但整棵树的形态不会边,换句话说,割掉每条边后,得到 ...
- 【刷题】洛谷 P3676 小清新数据结构题
题目背景 本题时限2s,内存限制256M 题目描述 在很久很久以前,有一棵n个点的树,每个点有一个点权. 现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方 ...
- 洛谷 P3676 小清新数据结构题
https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...
- Luogu3676 小清新数据结构题 动态点分治
传送门 换根类型的统计问题动态点分治都是很好做的. 设所有点的点权和为$sum$ 首先,我们先不考虑求$\sum\limits_i s_i^2$,先考虑如何在换根的情况下求$\sum\limits_i ...
- 洛谷 P3672 小清新签到题 [DP 排列]
传送门 题意:给定自然数n.k.x,你要求出第k小的长度为n的逆序对对数为x的1~n的排列 $n \le 300, k \le 10^13$ 一下子想到hzc讲过的DP 从小到大插入,后插入不会对前插 ...
- [P3676]小清新数据结构题
Description: 给你一棵树,每次询问以一个点为根时所有子树点权和的平方和 带修改 Hint: \(n\le 2*10^5\) Solution: 这题只要推出式子就很简单了 如果不换根这个平 ...
- [洛谷P3672]小清新签到题
题目描述 题目还是简单一点好. 给定自然数n.k.x,你要求出第k小的长度为n的逆序对对数为x的1~n的排列a1,a2...an,然后用仙人图上在线分支定界启发式带花树上下界最小费用流解决问题,保证存 ...
随机推荐
- redis一主二从三哨兵
redis做集群的时候有很多种配置方法,一主二从三哨兵这种模式是官网推荐的.,写配置文件链接的时候,写的是哨兵地址,不是IP,用户名,密码之类的. 一主二从很好理解,一个主的redis,实时备份到两个 ...
- ubuntu 安装google输入法
第五步:通常情况下,IBus图标(一个小键盘)会出现在桌面右上角的任务栏中.有时候这个图标会自行消失,可使用以下命令,找回消失的IBus图标: ibus-daemon -drx 不建议用googl ...
- 为阿里云ECS服务器二级域名绑定tomcat子目录,实现一个IP多个二级域名
摘要:前几天租了阿里云ECS服务器,选择的Windows系统,并在服务器上部署了tomcat服务器,随后我又买了一个域名,可一个域名只能指向一个IP地址,包括二级域名也只能指向一个IP地址,并不能指向 ...
- cudnn 安装
ubuntu 下载地址 https://developer.nvidia.com/rdp/cudnn-download 安装教程 http://docs.nvidia.com/deeplearning ...
- LUA Metatables
__index:当我们访问一个表中的元素不存在时,则会触发去寻找__index元方法,如果不存在,则返回nil,如果存在,则返回结果. 博主注:__index有点像异常处理的意思 __newindex ...
- Emacs及扩展配置
Emacs及扩展配置 Table of Contents 1. 动机之反思 2. 它山之石 3. 扩展的管理 4. 我额外安装的通用扩展(在purcell基础上) 5. LaTex相关的问题和配置 6 ...
- Binary Watch二进制时间
[抄题]: A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the b ...
- 给力分享新的ORM => Dapper( 转)
出处:http://www.cnblogs.com/sunjie9606/archive/2011/09/16/2178897.html 最近一直很痛苦,想选一个好点的ORM来做项目,实在没遇到好的. ...
- Zabbix部署与使用
*******需要配置网易YUM源来安装相关依赖包: [local_yum] name=local_yum baseurl=http://mirrors.163.com/centos/6/os/x86 ...
- FORM 错误:此责任无可用函数。 更改责任或与您的系统管理员联系。
错误:此责任无可用函数. 更改责任或与您的系统管理员联系. 2014-07-02 12:20:47 分类: Oracle Symptom 访问Help->Diagnostics->Exam ...