题目大意:给你一颗n个节点的树,最初点集S为空. 有m次操作:往当前点集S中加入/删除一个点,询问点x至集合S中任意点的最小距离,回到第t次修改点集的操作后的状态. 数据范围:$n,m≤10^5$ 我们先无视这个可持久化的要求,考虑下不可持久化怎么做. 显然考虑动态树分治. 令点v为当前分治中心,u为v在点分树上的父亲, 每个点开一个数组D,D[x]表示以v为根的点分树中,与v距离为不大于x的点的标记点数量. 我们借助这个数组,可以方便地求出从v走最少多少步可以走到一个标记点. 首先考虑查询操作…
可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域,这样就节省了大量的空间,使得可持久化数据结构的实现成为了可能. 如下图,就是可持久化链表 插入前 插入后 尽可能利用历史版本和当前版本的相同区域来减少空间的开销. 而主席树(可持久化线段树)的原理同样是这样. 有n个数字,  我们将其离散化,那么总有[1,n]个值,如果建一棵线段树,每个结点维护子…
[HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作完之后有q个询问,询问新树上两点之间的距离 \(n,m,q \leq 1 \times 10^5\) 分析 显然直接把所有节点存下来是不行的,因为节点的个数最多可以到\(10^{10}\).发现本质不同的子树只有n个,我们考虑把子树缩成一个点,构造一棵新树. 新树上的点有3种编号,注意区分: ​ 1…
题意:给定一个数组,每次查询第l到r区间的第k大值 解法嘛,当然是主席树,主席树即可持久化线段树,什么叫可持久化呢,就是指能够访问历史版本的数据结构,那么对于某些只能离线处理的题目强制在线之后 ,可以通过在线处理操作 经过这题总算对可持久化线段树有了些了解,我们开始先建一颗空树,然后对于每次修改我们只会修改logn个点,我们可以新建logn个来避免每次都新建一颗线段树导致的爆空间, 对于这题来说我们线段树中维护的是这个区间的点的个数,插入的时候按权值大小插入,对于l到r我们可以通过1-r减去1-…
题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j<k<i,且sj<sk<si 把每个三元组看作二维平面上的一个点(i,si) 先不考虑t, 那么j若满足要求,必须满足以(j,sj)为左下角,以(i,si)为右上角的矩形内没有其他的三元组 可以用CDQ分治解决 设三元组e[i]的坐标为(x,y)=(i,si) 先将所有的三元组按s排序,然后按…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyLex/p/7281110.html 看了看它的两道例题,就没写. 特殊商品可以直接用可持久化trie做. 其他部分用线段树分治.修改是单点的,询问是区间,原来想的是把询问区间定位后有 mlogn 个,在线段树的每个叶子上贡献一番:结果TLE了,因为若是在叶子处贡献,一个询问就要做 r-l+1 次.…
[FJOI2015]火星商店问题 前天考了到线段树分治模板题,全场都切了,就我不会QAQ 于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了." 第一道线段树分治题,看了yyb博客,学习了一波. 其实线段树分治就是对操作的时间分治. 对线段树每个节点开一个\(vector\),把询问的区间(时间的区间)看成一段一段放到线段树的\(vector\)里面存着. 注意到修改会延续到最后一刻,所以修改只是左端点不一样而已,相当于一个后缀. 把修改按照位置排序(这个时…
闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义下的. 不过叫它线段树分治挺形象的啊! 线段树分治思想 我们在做CDQ的时候,将询问和操作通通视为元素,在归并过程中统计左边的操作对右边的询问的贡献. 而在线段树分治中,询问被固定了.按时间轴确定好询问的序列以后,我们还需要所有的操作都会影响一个时间区间.而这个区间,毫无疑问正好对应着询问的一段区间…
题意 https://www.lydsy.com/JudgeOnline/problem.php?id=4771 思路 和 HDU 3333 其实有点像,不过是把序列的问题放在了树上,多维护一个深度即可.每个点用一个线段树维护子树内每个深度有多少种颜色(同样只保留每个颜色最浅位置),用线段树合并进行合并,由于要保留之前的颜色,所以合并应该可持久化. 为了将相同的颜色去除,再开一个线段树维护每个颜色目前的深度,若合并时出现重复情况,把深的颜色删去(也在维护深度的线段树中删去),代码比较难调. 代码…
传送门主席树 #include <bits/stdc++.h> #define int long long using namespace std; const int maxn=2e5+5; int n,m,a[maxn]; vector<int> v;//从0开始编号 inline int getid(int x)//得到值为x的编号 { return lower_bound(v.begin(),v.end(),x)-v.begin()+1;//lower_bound找到第一个…