[luogu3676] 小清新数据结构题 [树链剖分+线段树]
题面
思路
本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的
所以只能另辟蹊径
首先,我们考虑询问点都在1的情况
考虑一次修改带来的影响:
假设当前节点的值变动量为$delta$,修改节点为$u$
那么对于所有位于路径$(1,u)$上的节点而言,它们的子树和以及子树平方和都会有改变
设$sum(u)$表示子树点权和,$sumsqr(u)$表示点权和的平方
那么$\forall v \in (1,u)$,$sum(v)+=delta$,$sumsqr(v)+=delta\ast 2\ast sum(v)+delta\ast delta$
又可见$ans=\sum_{u} sumsqr(u)$
那么$ans$在这次事件中的变化量可以表示如下:
设$len$为路径$(1,u)$的长度
那么$ans+=len\ast delta\ast delta+delta\ast 2\ast \sum_{v \in (1,u)} sum(v)$
所以,我们可以使用一棵线段树维护$sum(u)$的值,树链剖分一下,只需要支持区间修改和区间查询
接下来考虑询问点在$x$的情况
可以发现,如果我们考虑$ans(1)$到$ans(x)$中各个位置的贡献,容易发现,依然只有$v\in (1,x)$的节点贡献改变了
设$a_i$表示节点$i$在以1为根(也就是我们的树剖维护的东西)时的子树点权和,$b_i$表示以$x$为根的时候的点权和,$sum$为总点权和
可以得到:
$ans(x)=ans(1)-\sum_{v\in (1,x)} a_v^2 +\sum_{v\in (1,x)} b_v^2$
同时,$a_i$和$b_i$有一个性质:
$a_1=b_x=sum=a_v+b_{fa(v)}$,其中$v \neq 1,x$
那么化简上面式子
$ans(x)=ans(1)-\sum_{v\in (1,x),v\neq 1}a_v^2 + sum_{v\in(1,x),v\neq x}b_v^2$
为了方便,我们用$a_i$表示路径上的第$i$个点,$b_i$同理
$ans(x)=ans(1)-\sum_{i=2}{len}a_i2 + sum_{i=2}{len}(sum-a_i)2$
$ans(x)=ans(1)+(len-1)\ast (len-1)\ast sum-2\ast (len-1)ast \sum_{i=2}^{len}a_i$
这样就可以算了,依然是树链剖分+线段树解决
注意最后面这个式子,如果为了方便直接查询到根,可以把$len-1$提出来,并把后面的$i=2...len$变成$1...len$,在前面把一个$len-1$变成$len+1$,即:
$ans(x)=ans(1)+(len-1)\ast ((len+1)\ast sum-2\ast \sum_{i=1}^{len}a_i)$
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#define ll long long
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,first[200010],dep[200010],siz[200010],son[200010],top[200010],pos[200010],back[200010],fa[200010],clk,cnte;
struct edge{
int to,next;
}a[400010];
ll w[200010],s[200010],ans1;
inline void adde(const int u,const int v){
a[++cnte]=(edge){v,first[u]};first[u]=cnte;
a[++cnte]=(edge){u,first[v]};first[v]=cnte;
}
void dfs1(const int u,const int f){
int i,v,maxn=0;
dep[u]=dep[f]+1;fa[u]=f;
siz[u]=1;son[u]=0;s[u]=w[u];
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==f) continue;
dfs1(v,u);
siz[u]+=siz[v];s[u]+=s[v];
if(maxn<siz[v]) son[u]=v,maxn=siz[v];
}
}
void dfs2(const int u,const int t){
int i,v;
pos[u]=++clk;back[clk]=u;top[u]=t;
if(son[u]) dfs2(son[u],t);
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
ll len[800010],sum[800010],lazy[800010];
void update(int num){
sum[num]=sum[num<<1|1]+sum[num<<1];
}
void push(int l,int r,int num){
if(l==r||!lazy[num]) return ;
int mid=(l+r)>>1;
sum[num<<1]+=(ll)(mid-l+1)*lazy[num];
sum[num<<1|1]+=(ll)(r-mid)*lazy[num];
lazy[num<<1]+=lazy[num];
lazy[num<<1|1]+=lazy[num];
lazy[num]=0;
}
int ql,qr;ll val;
void build(const int l,const int r,const int num){
if(l==r){sum[num]=s[back[l]];return;}
const int mid=(l+r)>>1;
build(l,mid,num<<1);build(mid+1,r,num<<1|1);
update(num);
}
void change(const int l,const int r,const int num){
if(l>=ql&&r<=qr){
sum[num]+=(r-l+1)*val;
lazy[num]+=val;
return;
}
push(l,r,num);
const int mid=(l+r)>>1;
if(mid>=ql) change(l,mid,num<<1);
if(mid<qr) change(mid+1,r,num<<1|1);
update(num);
}
ll query(const int l,const int r,const int num){
if(l>=ql&&r<=qr) return sum[num];
push(l,r,num);
const int mid=(l+r)>>1;ll re=0;
if(mid>=ql) re+=query(l,mid,num<<1);
if(mid<qr) re+=query(mid+1,r,num<<1|1);
return re;
}
void add(int u,const int v){
int f;val=v;
while(u){
f=top[u];
ql=pos[f];qr=pos[u];
change(1,n,1);
u=fa[f];
}
}
ll ask(int u){
int f;ll re=0;
while(u){
f=top[u];
ql=pos[f];qr=pos[u];
re+=query(1,n,1);
u=fa[f];
}
return re;
}
int main(){
n=read();int Q=read(),i,t1,t2,t3;ll s1;
memset(first,-1,sizeof(first));
for(i=1;i<n;i++){
t1=read();t2=read();
adde(t1,t2);
}
for(i=1;i<=n;i++) w[i]=read();
dfs1(1,0);dfs2(1,0);build(1,n,1);
for(i=1;i<=n;i++) ans1+=s[i]*s[i];
while(Q--){
t3=read();t1=read();
if(t3==1){
t2=read();
t2=t2-w[t1];w[t1]+=t2;
ans1+=t2*t2*dep[t1]+t2*2*ask(t1);
add(t1,t2);
}
else{
ql=qr=1;s1=query(1,n,1);
printf("%lld\n",ans1+s1*((dep[t1]+1)*s1-2*ask(t1)));
}
}
}
[luogu3676] 小清新数据结构题 [树链剖分+线段树]的更多相关文章
- 【bzoj4127】Abs 树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
- 【Codeforces827D/CF827D】Best Edge Weight(最小生成树性质+倍增/树链剖分+线段树)
题目 Codeforces827D 分析 倍增神题--(感谢T*C神犇给我讲qwq) 这道题需要考虑最小生成树的性质.首先随便求出一棵最小生成树,把树边和非树边分开处理. 首先,对于非树边\((u,v ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- B20J_2836_魔法树_树链剖分+线段树
B20J_2836_魔法树_树链剖分+线段树 题意: 果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u].初始时,这个果树的每个节点上都没有果子(即0个果子). Add u v d ...
- B20J_2243_[SDOI2011]染色_树链剖分+线段树
B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...
随机推荐
- iOS之旅--隐藏(去除)导航栏底部横线
iOS之旅--隐藏(去除)导航栏底部横线 iOS开发大部分情况下会使用到导航栏,由于我司的app导航栏需要与下面紧挨着的窗口颜色一致,导航栏底部的横线就会影响这个美观,LZ使用了以下方法.觉得不错,分 ...
- int ,long long 范围
类型名称 字节数 取值范围signed char 1 -128-+127short int 2 -32768-+32767int 4 -2147483648-+2147483647(10位数 2^31 ...
- 神经网络系列学习笔记(四)——神经网络之RNN学习笔记
不同于传统的FNNs(Feed-forward Neural Networks,前向反馈神经网络),RNNs引入了定向循环,能够处理那些输入之间前后关联的问题. RNNs的目的是用来处理序列数据. 具 ...
- JavaScript 事件机制
1 什么是事件 JavaScript 使我们有能力创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触发 JavaScript 函数的事件.比方说,我 ...
- Python中的str
str_lst = [ ('元素替换',), ('字符串切片',), ('字符串分割',), ('字符串连接',), ('元素计数',), ('寻找元素',), ('判断字符串的开头与结尾',), ( ...
- flask项目实战--论坛
项目结构搭建 1:用pycharm创建flask bbs项目 2:分别创建config.py.exts.py.models.py.manage.py文件 创建一个apps包存放前台,后台,公共的模块 ...
- 找回被丢弃怎么找都找不回来的git中的commit
崩溃的一天,打算提代码走人,结果切分支之后,commit丢了= =,找了三个多小时 接下来分享下如何找回丢失的commit的 打开项目所在位置,打开git bash,在gitBASH中输入 git f ...
- storm实时计算实例(socket实时接入)
介绍 实现了一个简单的从实时日志文件监听,写入socket服务器,再接入Storm计算的一个流程. 源码 日志监听实时写入socket服务器 package socket; import java ...
- CodeForces 873F Forbidden Indices 后缀数组
忘了当时怎么做的了,先把代码贴上,保存一下后缀数组模板. #include <cstdio> #include <cstring> #include <algorithm ...
- 《1024伐木累》-小白篇之丽jie(结束篇)-总章节六
往期回顾: 机缘巧合,月侠发现了老王和他心仪女孩儿的秘密,这让他倍感愤怒,一年以后,丽姐又在去往老王家的路上,这让月侠感到历史即将重新上演,他想拦住丽姐,可恰巧丽姐手机没电,失去了联系. 小序 有人 ...