初见安~这里是传送门:洛谷P6329 【模板】点分树 | 震波

一、点分树

其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树。

比如当前点是u,求出子树v的重心root后将root与u连边。如此递归下去,就是一棵点分树。

有什么用呢?因为重构了树的结构,并且保证了深度不超过logn,所以可以把一些极其暴力的操作的复杂度变正确。

比如震波这个题。

二、题解

题意很显然:单点修改和求距某点距离在K以内的所有点的点权和

借用点分树的性质,我们建树过后考虑如何维护这个暴力(不容易想到 算是点分树自带的套路?)。另表示点u在点分树上的子树内距离在i以内的点的点权和。注意,这里可能对产生贡献的点是u在点分树上的子树内的点,但是距离是原树的距离。我们先不考虑修改,如果是询问的话,显然可以用统计一部分的点。但是因为是重构过的,所以有可能有些点还在上面,所以我们要挨着往上走,也就是从u暴力跳到整个点分树的树根去。并且点分树上点在原树上不一定相邻,所以对于当前某个父亲x,所求为距离点u距离为K以内的点的点权和,x的贡献为

到这里就会有个问题:是否存在这样一个被统计到的点v,fa[u]是点分树上u的父亲,路径u->fa[u]->v有重复经过某条边,但依旧在K以内导致v被计算了两次?那必然存在。考虑如何容斥掉这种情况。其实这种重复的情况出现只有当原树上u、v、fa[u]是这样的祖先关系时才会出现(大概?)也就是,v是u的祖先,fa[u]又是v的祖先。这样的话如果会重复遍历,那么点分树上v一定在u的子树内。换言之,我们会重复遍历到v完全是因为在u的时候计算过了一次,在又计算了一次。所以减去u子树内对fa[u]的贡献即可。换言之我们再搞一个表示点分树上u的子树内的点到fa[u]距离为i的点的点权和。容斥掉即可。

修改也很容易,因为每个点的点权会影响到的就只有它的所有祖先,是log级别的。暴力跳上去就好。

但是这个题因为求的是前K个,所以需要一个前缀和。这个就用树状数组了,总的时间复杂度多一个log,为nlog^2n。

以及,因为n个点,每个点都有一个树状数组,空间不可能开n^2,所以考虑实际距离应该在size[u]以内,卡着子树大小size[u]开就好。空间复杂度也是nlogn的。(可是我卡着开就全RE了不知道为什么……)

上代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 100005
using namespace std;
typedef long long ll;
int read() {int x = 0, f = 1, ch = getchar();while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();return x * f;
}struct edge {int to, nxt;} e[maxn << 1];
int head[maxn], k = 0;
void add(int u, int v) {e[k] = {v, head[u]}; head[u] = k++;}int n, m, a[maxn];
int dep[maxn], st[maxn << 1][20], num[maxn], tot = 0;
int get_min(int a, int b) {return dep[a] < dep[b]? a : b;}
void dfs(int u, int fa) {st[++tot][0] = u; num[u] = tot;for(int i = head[u], v; ~i; i = e[i].nxt) {v = e[i].to; if(v == fa) continue;dep[v] = dep[u] + 1; dfs(v, u); st[++tot][0] = u;}
}int root, size[maxn], part[maxn], max_part, all_part = 0;
bool vis[maxn];
void get_root(int u, int fa) {size[u] = 1; part[u] = 0; all_part++;for(int i = head[u], v; ~i; i = e[i].nxt) {v = e[i].to; if(v == fa || vis[v]) continue;get_root(v, u); size[u] += size[v];part[u] = max(part[u], size[v]);}part[u] = max(part[u], max_part - size[u]);if(part[u] < part[root]) root = u;
}int sz[maxn], fa[maxn];
vector<int> t[maxn][2];
void slv(int u) {vis[u] = true; sz[u] = all_part + 1;//allpart是求重心的时候算的整个子树大小,但是要+1才行,按理说不该有这么远的点……?QwQt[u][0].resize(sz[u] + 1); t[u][1].resize(sz[u] + 1);//这里+1是因为算上0位置for(int i = head[u], v; ~i; i = e[i].nxt) {v = e[i].to; if(vis[v]) continue;max_part = size[v]; all_part = root = 0; get_root(v, u);fa[root] = u; slv(root);}
}int get_dis(int u, int v) {register int x = num[u], y = num[v]; if(x > y) swap(x, y);register int len = (int)log2(y - x + 1), lca = get_min(st[x][len], st[y - (1 << len) + 1][len]);return dep[u] + dep[v] - (dep[lca] << 1);
}
//两行树状数组
void ist(int u, int op, int x, int w) {x++; for(; x <= sz[u]; x += (x & -x)) t[u][op][x] += w;}
int ask(int u, int op, int x) {x++; int res = 0; for(x = min(x, sz[u]); x; x -= (x & -x)) res += t[u][op][x]; return res;}
void update(int u, int val) {//楼上树状数组,求答案的时候一定记得上界取minfor(int i = u; i; i = fa[i]) ist(i, 0, get_dis(u, i), val);for(int i = u; fa[i]; i = fa[i]) ist(i, 1, get_dis(u, fa[i]), val);
}signed main() {n = read(), m = read(); memset(head, -1, sizeof head);for(int i = 1; i <= n; i++) a[i] = read();for(int i = 1, u, v; i < n; i++) u = read(), v = read(), add(u, v), add(v, u);dfs(1, 0);root = 0, max_part = part[0] = n; get_root(1, 0);slv(root);//建点分树dep[0] = n + n;for(int i = 1; (1 << i) <= tot; i++) for(int j = 1; j + (1 << i) <= tot; j++) st[j][i] = get_min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);//O1求LCA,st表for(int i = 1; i <= n; i++) update(i, a[i]);//更新值int ans = 0;while(m--) {register int op = read(), x = read(), y = read();x ^= ans, y ^= ans;if(!op) {ans = ask(x, 0, y);for(int i = x; fa[i]; i = fa[i]) {register int d = get_dis(x, fa[i]);//往上跳。因为点分树距离不单调所以都要求if(y >= d) ans += ask(fa[i], 0, y - d) - ask(i, 1, y - d);}printf("%d\n", ans);} else update(x, y - a[x]), a[x] = y;}return 0;
}

迎评:)
——End——

洛谷·【模板】点分树 | 震波【including 点分树相关推荐

  1. [BZOJ4889][洛谷P3759][TJOI2017]不勤劳的图书管理员 分块+树状数组

    题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打乱顺序的书, ...

  2. 模拟退火总结+洛谷模板题(P1337 [JSOI2004]平衡点 / 吊打XXX)

    原来就听说过模拟退火,然后一直觉得神奇,但是没有真正的去实现这个算法. 模拟退火对TSP之类的问题很实用. 1.概念:模拟退火算法(Simulate Anneal,SA)是一种通用概率演算法,用来在一 ...

  3. 洛谷模板,树状数组二 差分

    题目链接:https://www.luogu.org/problemnew/show/P3368 先介绍下差分: 设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5} ...

  4. 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)

    题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做"LC ...

  5. 洛谷P3987 我永远喜欢珂朵莉~(set 树状数组)

    题意 题目链接 Sol 不会卡常,自愧不如.下面的代码只有66分.我实在懒得手写平衡树了.. 思路比较直观:拿个set维护每个数出现的位置,再写个线段树维护区间和 #include<bits/s ...

  6. 洛谷P3987 我永远喜欢珂朵莉~ 树状数组+vector(暴力)

    题目链接:我永远喜欢珂朵莉- 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到 ...

  7. 洛谷 P2468 粟粟的书架 二分(主席树+前缀和)

    传送~:https://www.luogu.org/problem/P2468 看了一下数据也发现是两道题,后边当他是一个序列(n==1)的时候直接主席树二分区间前k大和就行了 但是有一个细节我觉得就 ...

  8. dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)

    qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...

  9. 【洛谷5251】[LnOI2019] 第二代图灵机(线段树+ODT)

    点此看题面 大致题意: 有单点修改数字和区间着色两种修改操作,询问你某段区间内包含所有颜色且数字和最小的子区间的数字和,或某段区间内没有重复颜色且数字和最大的子区间的数字和.数据随机. \(ODT\) ...

  10. 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...

最新文章

  1. 将现有网站与Community Server2.0整合解决方案(原创)
  2. 如何在DataFrame索引某一行
  3. mysql删除以什么开头的数据_Mysql如何删除以“#sql-”开头的临时表
  4. sci translate好用吗_228个学科分类对应12000+本SCI和SSCI期刊,总有你要的那款!
  5. php 图片无法删除,php如何删除上传的图片
  6. spring-boot-admin 2.0小试牛刀
  7. linux终端下的网页浏览器w3m
  8. python如何使用 b_python中的b
  9. Elasticsearch系列——实战探索text与keyword的区别
  10. 人口预测模型基础介绍
  11. 2014年最新珍藏版XP系统GHO镜像文件下载,史上驱动最齐全XP终结版(定时更新)
  12. C. Not Adjacent Matrix
  13. Brew doctor warns about “Warning: A newer Command Line Tools release is available”
  14. 第四章 DirectX 渲染流水线(上)
  15. Mahony算法 AHRS系统
  16. 简易图书管理系统(主要是jsp+servlet的练习),基于jsp+servlet的图书管理系统
  17. 三维电影特效动画制作软件——Houdini 17.5
  18. php 输出gif 不动,PS制做的gif动画导出后动图不动了怎么办?
  19. JavaWeb简单的单点登录、验证码校验功能实现
  20. 用DIV+CSS技术设计的鲜花网站(web前端网页制作课作业)

热门文章

  1. HP laserJet Pro MFP M126nw打印机连接无线设置
  2. windows -- dos命令
  3. Elasticsearch 跨网络、跨集群同步选型指南
  4. Linux 关机/重启指令
  5. python怎么画出圆润的曲线_sklearn画ROC曲线方法总结1(plot_roc_curve)
  6. 在内网建一个FTP服务器,并且可以通过外网访问
  7. 人还是要有幻想的(22)
  8. RabbitMq第三种模型--fanout
  9. 解决MSN无法登陆的故障
  10. aspectJ动态编入问题