Luogu3676 小清新数据结构题 动态点分治
换根类型的统计问题动态点分治都是很好做的。
设所有点的点权和为$sum$
首先,我们先不考虑求$\sum\limits_i s_i^2$,先考虑如何在换根的情况下求$\sum\limits_i s_i$。
考虑一个点$i$会被统计多少次,显然是$dep_i+1$,那么$\sum\limits_i s_i = \sum\limits_i (dep_i+1) \times val_i = \sum\limits_i dep_i \times val_i + sum$。
$\sum\limits_i dep_i \times val_i$是不是似曾相识……其实就是幻想乡战略游戏
接着我们考虑这个烦人的平方项。那么我们还需要推一个结论:换根不会影响$W=\sum\limits_i s_i \times (sum - s_i)$的值。
证明如下:
我们考虑$K = \sum\limits_i \sum\limits_j val_i \times val_j \times dis(i,j)$,意思就是取两个点,将中间的所有边设为两边的点的权值之积然后相加。显然这一个值是不会因为根的变化而改变的。
接着我们考虑一条边$(x,y)$对$K$的贡献,显然是这条边分割开来的两个子树的权值和的乘积,而无论根是哪一个,这两个子树中必定有且仅有一个是树的一个子树,假设$x$对应的树是子树,它就代表着$s_x \times (sum - s_x)$,把所有边的贡献加起来就是$W=\sum\limits_i s_i \times (sum - s_i)=\sum\limits_i \sum\limits_j val_i \times val_j \times dis(i,j)$,所以$W$是不会因为根的变化而变化的。
而$W=\sum\limits_i s_i \times (sum - s_i) = sum \times \sum\limits_i s_i - \sum\limits_i s_i^2$,那么$\sum\limits_i s_i^2 = sum \times \sum\limits_i s_i - W$
接着我们考虑修改点权对$W$的影响。由$\Delta W = \Delta v \times \sum\limits_j val_j \times dep_j$,实质跟上面计算$\sum\limits_i s_i$的方法一样。
#include<bits/stdc++.h>
#define int long long
//This code is written by Itst
using namespace std;
inline int read(){
;
;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return f ? -a : a;
}
;
struct Edge{
int end , upEd;
}Ed[MAXN << ];
] , dis[MAXN][] , dep[MAXN];
][MAXN << ] , fir[MAXN] , logg2[MAXN << ] , size[MAXN] , cur[MAXN] , up[MAXN] , sum[MAXN];
int cntEd , N , M , minSize , nowSize , minInd , cntST , W , allV;
bool vis[MAXN];
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
void init_dfs(int x , int p){
dep[x] = dep[p] + ;
fir[x] = ++cntST;
sum[x] = val[x];
ST[][cntST] = x;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p){
init_dfs(Ed[i].end , x);
ST[][++cntST] = x;
sum[x] += sum[Ed[i].end];
}
W += sum[x] * (allV - sum[x]);
}
inline int cmp(int a , int b){
return dep[a] < dep[b] ? a : b;
}
void init_st(){
; i <= cntST ; ++i)
logg2[i] = logg2[i >> ] + ;
; << i <= cntST ; ++i)
; j + ( << i) - <= cntST ; ++j)
ST[i][j] = cmp(ST[i - ][j] , ST[i - ][j + ( << (i - ))]);
}
inline int LCA(int x , int y){
x = fir[x];
y = fir[y];
if(x > y)
swap(x , y);
];
<< t) + ]);
}
inline int calcLen(int x , int y){
);
}
void getSize(int x){
vis[x] = ;
++nowSize;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
getSize(Ed[i].end);
vis[x] = ;
}
void getRoot(int x){
vis[x] = size[x] = ;
;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
getRoot(Ed[i].end);
maxN = max(maxN , size[Ed[i].end]);
size[x] += size[Ed[i].end];
}
maxN = max(maxN , nowSize - size[x]);
if(maxN < minSize){
minSize = maxN;
minInd = x;
}
vis[x] = ;
}
void init_dfz(int x , int p){
nowSize = ;
minSize = 0x7fffffff;
getSize(x);
getRoot(x);
x = minInd;
fa[x][] = x;
fa[x][] = p;
vis[x] = ;
sum[x] = val[x];
; fa[x][i] ; ++i){
fa[x][i + ] = fa[fa[x][i]][];
dis[x][i] = calcLen(fa[x][i] , x);
up[fa[x][i - ]] += dis[x][i] * val[x];
sum[fa[x][i]] += val[x];
cur[fa[x][i]] += dis[x][i] * val[x];
}
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
init_dfz(Ed[i].end , x);
}
void init(){
init_dfs( , );
init_st();
init_dfz( , );
}
inline int query(int x){
int all = cur[x];
; fa[x][i] ; ++i){
all += cur[fa[x][i]] - up[fa[x][i - ]];
all += (sum[fa[x][i]] - sum[fa[x][i - ]]) * dis[x][i];
}
return all;
}
inline void modify(int x , int v){
W += (v - val[x]) * query(x);
allV += v - val[x];
sum[x] += v - val[x];
; fa[x][i] ; ++i){
up[fa[x][i - ]] += (v - val[x]) * dis[x][i];
cur[fa[x][i]] += (v - val[x]) * dis[x][i];
sum[fa[x][i]] += v - val[x];
}
val[x] = v;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("3676.in" , "r" , stdin);
freopen("3676.out" , "w" , stdout);
#endif
N = read();
M = read();
; i < N ; ++i){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
; i <= N ; ++i){
val[i] = read();
allV += val[i];
}
init();
; i <= M ; ++i)
){
int x = read() , y = read();
modify(x , y);
}
else
cout << allV * (query(read()) + allV) - W << '\n';
;
}
Luogu3676 小清新数据结构题 动态点分治的更多相关文章
- 洛谷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.可以发现只要维护每个点到 ...
- 【Luogu3676】小清新数据结构题(动态点分治)
[Luogu3676]小清新数据结构题(动态点分治) 题面 洛谷 题解 先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护. 做法大概是这样: 我们先以任意一个点为根,把当前点看成是一棵有根 ...
- 洛谷 P3676 - 小清新数据结构题(动态点分治)
洛谷题面传送门 题目名称好评(实在是太清新了呢) 首先考虑探究这个"换根操作"有什么性质.我们考虑在换根前后虽然每个点的子树会变,但整棵树的形态不会边,换句话说,割掉每条边后,得到 ...
- 【刷题】洛谷 P3676 小清新数据结构题
题目背景 本题时限2s,内存限制256M 题目描述 在很久很久以前,有一棵n个点的树,每个点有一个点权. 现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方 ...
- 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)
传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...
- 洛谷 P3676 小清新数据结构题
https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...
随机推荐
- mysql 中表和数据库名称不要使用 '-' 命名
mysql 中表和数据库名称不要使用 '-' 命名 若使用这个符号,比如 my-name 做为数据库表名称 那么在 sql 中必须如下: select * from `my-name`
- loadrunner 场景设计-手工场景设计
场景设计-手工场景设计 by:授客 QQ:1033553122 概述 通过选择需要运行的脚本,分配运行脚本的负载生成器,在脚本中分配Vuser来建立手工场景 手工场景就是自行设置虚拟用户的变化,主要是 ...
- MQTT详解以及在IoT中的应用
MQTT定义: MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台, ...
- Android 打开文件或文件夹777权限
打开777权限 public class SystemManager extends Activity { public static boolean RootCommand(String comma ...
- 将 Azure VM 迁移到 Azure 中的托管磁盘
Azure 托管磁盘无需单独管理存储帐户,从而简化了存储管理. 还可以将现有的 Azure VM 迁移到托管磁盘,以便受益于可用性集中 VM 的更佳可靠性. 它可确保可用性集中不同 VM 的磁盘完全相 ...
- 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之@classmethod,@staticmethod
定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...
- asp.net webapi 自定义身份验证
/// <summary> /// 验证 /// </summary> /// Account API账号 /// TimeStamp 请求时间 /// Sign 所有请求参数 ...
- 在 vs2017 中使用 C# 7 新特性。
几个概念区分: 1.C# C# 是一种.net 语言,与此类似的还有 vb,F#.不同版本的语言要配合相应的解释器才能发挥作用.目前 最新版本 为 C# 7.3. 2.VS VS 是 ...
- Python3编写网络爬虫05-基本解析库XPath的使用
一.XPath 全称 XML Path Language 是一门在XML文档中 查找信息的语言 最初是用来搜寻XML文档的 但是它同样适用于HTML文档的搜索 XPath 的选择功能十分强大,它提供了 ...
- Java设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...