题目链接

洛谷P3676

题解

我们先维护\(1\)为根的答案,再考虑换根

一开始的答案可以\(O(n)\)计算出来

考虑修改,记\(s[u]\)表示\(u\)为根的子树的权值和

当\(u\)节点产生\(v\)的增量时,只影响\(1\)到\(u\)路径上的\(s\),权值和都\(+v\)

而对答案的影响是

\[\begin{aligned}
\Delta ans &= \sum\limits_{i}^{k}(s_i + v)^{2} - \sum\limits_{i = 1}^{k} s_i^2 \\
&= 2v\sum\limits_{i = 1}^{k}s_i + v^{2}k
\end{aligned}
\]

所以只需维护路径上\(s\)的和即可更新答案

使用树剖 + BIT或者线段树

考虑如何换根

考虑从\(1\)到\(u\)经历了什么

发现同样只有\(1\)到\(u\)路径上的点的贡献产生了变化

设\(a_i\)表示当\(1\)为根时,路径上第\(i\)个点的子树权值和

设\(b_i\)表示当\(u\)为根时,路径上第\(i\)个点的子树权值和

有等式

\[a_{i + 1} + b_i = a_1 = b_k
\]

\[\begin{aligned}
ans_u &= ans_1 - \sum\limits_{i = 1}^{k}a_i^{2} + \sum\limits_{i = 1}^{k}b_i^{2} \\
&= ans_1 - \sum\limits_{i = 1}^{k}a_i^{2} + \sum\limits_{i = 2}^{k}(a_1 - a_i)^{2} + a_1^2 \\
&= ans_1 - \sum\limits_{i = 2}^{k}a_i^{2} + \sum\limits_{i = 2}^{k}(a_1 - a_i)^{2} \\
&= ans_1 + (k - 1)a_1^{2} - 2a_1\sum\limits_{i = 2}^{k}a_i \\
&= ans_1 + s_1((k - 1)s_1 - 2(\sum\limits_{i = 1}^{k}s_i - s_1)) \\
&= ans_1 + s_1((k + 1)s_1 - 2\sum\limits_{i = 1}^{k}s_i)
\end{aligned}
\]

同样对\(\sum\limits_{i = 1}^{k}s_i\)求和就行了

复杂度\(O(nlog^2n)\)

\(BIT\)大法好

#include<algorithm>
#include<iostream>
#include<cstdio>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define lbt(x) (x & -x)
using namespace std;
const int maxn = 200005;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
return flag ? out : -out;
}
int n,Q,h[maxn],ne = 1;
int fa[maxn],top[maxn],siz[maxn],dfn[maxn],son[maxn],dep[maxn],cnt;
LL S[maxn],SS[maxn],s[maxn],val[maxn],ans;
struct EDGE{int to,nxt;}ed[maxn << 1];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
void add(LL* s,int u,LL x){while (u <= n) s[u] += x,u += lbt(u);}
LL query(LL* s,int u){LL re = 0; while (u) re += s[u],u -= lbt(u); return re;}
void Add(int l,int r,LL v){
add(S,l,v); add(S,r + 1,-v);
add(SS,l,v * l); add(SS,r + 1,-v * (r + 1));
}
LL Query(int u){return 1ll * (u + 1) * query(S,u) - query(SS,u);}
LL Sum(int l,int r){return Query(r) - Query(l - 1);}
void dfs1(int u){
siz[u] = 1; s[u] = val[u];
Redge(u) if ((to = ed[k].to) != fa[u]){
fa[to] = u; dep[to] = dep[u] + 1; dfs1(to);
siz[u] += siz[to]; s[u] += s[to];
if (!son[u] || siz[son[u]] < siz[to]) son[u] = to;
}
}
void dfs2(int u,int flag){
dfn[u] = ++cnt; Add(cnt,cnt,s[u]);
top[u] = flag ? top[fa[u]] : u;
if (son[u]) dfs2(son[u],true);
Redge(u) if ((to = ed[k].to) != fa[u] && to != son[u])
dfs2(to,false);
}
void solve1(int u,LL v){
LL len = dep[u] + 1,tot = 0,x = u; v -= val[u]; val[u] += v;
while (x){
tot += Sum(dfn[top[x]],dfn[x]);
Add(dfn[top[x]],dfn[x],v);
x = fa[top[x]];
}
ans += 2ll * v * tot + v * v * len;
}
void solve2(int u){
LL tot = 0,s1 = Query(1),x = u,len = dep[u] + 1;
while (x) tot += Sum(dfn[top[x]],dfn[x]),x = fa[top[x]];
printf("%lld\n",ans + s1 * ((len + 1) * s1 - 2 * tot));
}
int main(){
n = read(); Q = read();
for (int i = 1; i < n; i++) build(read(),read());
REP(i,n) val[i] = read();
dfs1(1); dfs2(1,0);
REP(i,n) ans += s[i] * s[i];
int opt,x;
while (Q--){
opt = read(); x = read();
if (opt & 1) solve1(x,read());
else solve2(x);
}
return 0;
}

洛谷P3676 小清新数据结构题 【树剖 + BIT】的更多相关文章

  1. 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)

    传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...

  2. 洛谷 P3676 - 小清新数据结构题(动态点分治)

    洛谷题面传送门 题目名称好评(实在是太清新了呢) 首先考虑探究这个"换根操作"有什么性质.我们考虑在换根前后虽然每个点的子树会变,但整棵树的形态不会边,换句话说,割掉每条边后,得到 ...

  3. 【刷题】洛谷 P3676 小清新数据结构题

    题目背景 本题时限2s,内存限制256M 题目描述 在很久很久以前,有一棵n个点的树,每个点有一个点权. 现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方 ...

  4. 洛谷 P3676 小清新数据结构题

    https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...

  5. 洛谷P3676 小清新数据结构题 [动态点分治]

    传送门 思路 这思路好妙啊! 首先很多人都会想到推式子之后树链剖分+线段树,但这样不够优美,不喜欢. 脑洞大开想到这样一个式子: \[ \sum_{x} sum_x(All-sum_x) \] 其中\ ...

  6. [P3676]小清新数据结构题

    Description: 给你一棵树,每次询问以一个点为根时所有子树点权和的平方和 带修改 Hint: \(n\le 2*10^5\) Solution: 这题只要推出式子就很简单了 如果不换根这个平 ...

  7. [luogu3676] 小清新数据结构题 [树链剖分+线段树]

    题面 传送门 思路 本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的 所以只能另辟蹊径 首先,我们考虑询问点都在1的 ...

  8. 洛谷 P3672 小清新签到题 [DP 排列]

    传送门 题意:给定自然数n.k.x,你要求出第k小的长度为n的逆序对对数为x的1~n的排列 $n \le 300, k \le 10^13$ 一下子想到hzc讲过的DP 从小到大插入,后插入不会对前插 ...

  9. 并不对劲的p3676:小清新数据结构题

    题目大意 有一棵有\(n\)(\(n\leq 2*10^5\))个点的树,要进行\(q\)(\(q\leq 2*10^5\))次操作,每次操作是以下两种中的一种: 1.修改一个点的点权 2.指定一个点 ...

随机推荐

  1. Unity学习笔记(5):动态加载Prefab

    第一种方法,从Resources文件夹读取Prefab Assets/Resources文件夹是Unity中的一个特殊文件夹,在博主当前的认知里,放在这个文件夹里的Prefab可以被代码动态加载 直接 ...

  2. Swing的概述

    Swing在Java中是一个包,下面就是它的基本概述:简介: Java为了方便图形界面的实现, 专门设计了类库来满足各种各样的图形元素和用户交互事件, 该类库即为抽象窗口工具箱(Abstract Wi ...

  3. linux运维升级路线

    运维工程师是从一个呆逼进化为苦逼再成长为牛逼的过程,前提在于你要能忍能干能拼,还要具有敏锐的嗅觉感知前方潮流变化.如:今年大数据,人工智能比较火……(相对表示就是 Python 比较火) 之前写过运维 ...

  4. LeetCode 561. Array Partition I (C++)

    题目: Given an array of 2n integers, your task is to group these integers into npairs of integer, say ...

  5. 互评Alpha作品——Hello World!团队作品空天猎

    基于NABCD评论作品 1.Need需求:市面上同类型的手机及PC端飞行射击类游戏有很多,所以从需求方面来说,这款游戏的潜在客户非常有局限性.近些年较火的飞行射击类游戏,例如腾讯14年发行的<全 ...

  6. 第九次作业psp

    psp 进度条 代码累积折线图 博文累积折线图 psp饼状图

  7. (第十周)Beta Review会议

    项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 Beta Review会议 时间:2016.11.14   10:00——11:30.13:30——15:00 ...

  8. 09慕课网《进击Node.js基础(一)》HTTP-get/request

    get是对request封装 可以在后台发起http请求,获取远程资源,更新或者同步远程资源 http.request(options[,callback]) 以下代码灌水失败: var http = ...

  9. 用JAVA制作微型操作系统4月23日情况

    弄好了一个自认为十分精美的界面,但本想着昨天就在开始按钮上先套入控制jp222面板上的jb2标签上的时间更新,这按钮起到开始线程的作用(我认为按钮应该可以通过t.start()来触发线程,结果不知为什 ...

  10. java中static使用之静态方法注意点

    1.静态方法可以直接调用同类中的静态成员,但是不能直接调用非静态成员,这是为什么呢?大家想一下,静态成员在对象创建之前就要写入内存,所以它在内存中是实实在在的存在的,而非静态还不存在内存中,所以不能调 ...