随笔分类 -  数据结构-线段树

摘要:题意:01序列,区间反转,版本回退,求和 主席树(可持久化线段树)裸题,貌似我还没有写过带pushdown操作的主席树板子,就先贴一个在这里 注意在修改和pushdown操作的时候要新建结点 1 #include<bits/stdc++.h> 2 using namespace std; 3 typ 阅读全文
posted @ 2021-04-05 22:39 jrltx 阅读(62) 评论(0) 推荐(0)
摘要:题意:从数组a中找出一个区间[l,r]中只出现过一次的数 设pre[i]表示a[i]在i之前的上一次出现,a[i]在[l,r]中只出现过一次等价于pre[i]<l,所以只需在[l,r]中找出一个满足pre[i]<l的i就行了。由于还必须保证i是在[l,r]中最后一次出现,一棵线段树是实现不了的,需要 阅读全文
posted @ 2020-05-10 18:26 jrltx 阅读(212) 评论(0) 推荐(0)
摘要:题目链接 很明显的2SAT问题,和树上距离有关显然要考虑树分治。由于2-SAT不具有容斥性,点分治不方便处理,不过我们可以边分治。 边分治,分治过程中对每条边t左右两侧各建立一棵线段树,线段树上每个区间结点u(设代表的区间范围为[l,r])开两个条件结点p[u][0]和p[u][1],分别代表”边t 阅读全文
posted @ 2020-04-12 11:52 jrltx 阅读(284) 评论(1) 推荐(1)
摘要:题目链接 二维平面RMQ问题,单点修改,区间询问最大最小值 树套树或者四叉树均可做 树套树版本: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=500+10,mod=1e9 阅读全文
posted @ 2020-03-01 20:27 jrltx 阅读(183) 评论(0) 推荐(0)
摘要:题意:有n个忍者(编号为1-n),每个忍者有三个属性:横坐标x,纵坐标y,所属门派c,要求支持三种操作: 1.改变第k个忍者的位置 2.改变第k个忍者的门派 3.查询编号为[l,r]之间的忍者中,所属门派不同的两个忍者的最大曼哈顿距离 通过曼哈顿距离变换,将每个忍者的横坐标和纵坐标拆成x+y和x-y 阅读全文
posted @ 2019-10-12 17:00 jrltx 阅读(677) 评论(0) 推荐(0)
摘要:题意:有一棵树,树上每个结点上有一个字母,有两种操作: 1)询问树上两点u,v间有向路径上有多少个字母和某个固定的字符串相匹配 2)将结点u的字母修改为x 树剖+线段,暴力维护前缀和后缀哈希值(正反都要维护)以及区间内匹配的个数,合并两区间时判断一下跨过分界点的情况就行了。由于被匹配的字符串长度不超 阅读全文
posted @ 2019-10-04 20:02 jrltx 阅读(290) 评论(0) 推荐(0)
摘要:题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g)。 问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\sum\limits_{i<j}[g+1\leqslant |j-i|\leqslant g+LCP(i 阅读全文
posted @ 2019-09-17 15:30 jrltx 阅读(239) 评论(0) 推荐(0)
摘要:题意:给出棵树上的k条路径,求这些路径的公共点数量。 将每条路径上的点都打上标记,被标记过k次的点就是公共点了。由于公共点形成的区间是连续的,因此直接在线段树上暴搜即可在$O(logn)$求出一条链上公共点的数量。 怎样找被标记过k次的点呢?可以维护一个区间最大值mx和一个区间最小值mi,如果mx= 阅读全文
posted @ 2019-08-12 21:55 jrltx 阅读(305) 评论(0) 推荐(0)
摘要:题目链接 三种操作:区间加,区间开根号,区间求和。 修改的时候判断区间内的最大值和最小值是否相等或者差1,如果相等则变为区间赋值,否则再判断开根号之后的最大值和最小值是否相等,如果相等则区间赋值,否则区间加法。 这题的数据也忒恶心了点吧?本来直接判断相等就能解决的问题,非要加上一个玄学的优化才能过掉 阅读全文
posted @ 2019-06-28 14:30 jrltx 阅读(279) 评论(0) 推荐(0)
摘要:题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数。 dsu on tree/线段树合并裸题。 启发式合并1:(748ms) 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int 阅读全文
posted @ 2019-05-01 22:17 jrltx 阅读(251) 评论(0) 推荐(0)
摘要:题目链接 吉司机线段树裸题... 阅读全文
posted @ 2019-04-26 18:56 jrltx 阅读(147) 评论(0) 推荐(0)
摘要:题目链接 题意:在一条直线上依次建造n座建筑物,每座建筑物建造完成后询问它在多长的部分是最高的。 比较好想的方法是用线段树分别维护每个区间的最小值mi和最大值mx,当建造一座高度为x的建筑物时,若mi>x则答案无贡献,直接退出,若mx<=x则区间赋值为x,答案加上区间长度。其他情况需要继续递归搜索。 阅读全文
posted @ 2019-04-26 16:46 jrltx 阅读(342) 评论(0) 推荐(1)
摘要:题目链接 题意:n个人排成一列,一开始他们互不认识,每次选[l,r]上的人开party,使他们互相认识,求出每次party之后新互相认识的人的对数。 思路:把“互相认识”变成单向连边,只考虑左边的人对右边的贡献。对于每个人,他认识的人的区间必然是连续的,可以维护他认识的最右边的人R,这样更新操作相当 阅读全文
posted @ 2019-04-26 14:07 jrltx 阅读(444) 评论(0) 推荐(1)
摘要:题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum、最小前缀lsum、最小后缀rsum,枚举每个数a[i],设以a[i]为最小值的区间为[l,r] 若a[i]>0,则最优解就是a[i]*([l,r]的区间和 阅读全文
posted @ 2019-04-23 19:02 jrltx 阅读(541) 评论(0) 推荐(0)
摘要:题目链接 交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可。 感觉像是个带修改的二维偏序问题。(修改点$(x,y)$的值,维护和查询位于$(x_1,y_1)$与$(x_2,y_2)$之间的点的个数) 还有理论上能够AC 阅读全文
posted @ 2019-04-12 16:01 jrltx 阅读(216) 评论(0) 推荐(0)
摘要:题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的。 (据说线段树套线段树、树状数组套线段树也能过?) 阅读全文
posted @ 2019-04-11 20:00 jrltx 阅读(200) 评论(0) 推荐(0)
摘要:题目链接 权值线段树套区间线段树,权值线段树的每个结点存储该结点所表示的区间范围内的数在各个区间的分布情况,查询时在权值线段树上二分即可。复杂度$O(nlog^2n)$ 注意区间线段树需要动态开点,并且标记要永久化,否则会TLE。 另外就是sum可能会爆int,需要用long long存储。 阅读全文
posted @ 2019-04-10 19:45 jrltx 阅读(159) 评论(0) 推荐(0)
摘要:题目链接 对每个结点建立两棵线段树,一棵记录该结点的子树下每种颜色对应的最小深度,另一棵记录子树下的每个深度有多少结点(每种颜色的结点只保留最浅的深度即可),自底而上令父节点继承子结点的线段树,如果合并两棵颜色线段树时发现某种颜色重复,则在深度线段树上把较深的深度对应的位置-1。 注意由于强制在线, 阅读全文
posted @ 2019-04-09 15:37 jrltx 阅读(472) 评论(0) 推荐(0)
摘要:题目链接 本质是维护斜率递增序列。 用分块的方法就是把序列分成sqrt(n)块,每个块分别用一个vector维护递增序列。查询的时候遍历所有的块,同时维护当前最大斜率,二分找到每个块中比当前最大斜率大的那个点。修改的时候只需要修改点所在的那个块即可。复杂度$O(m\sqrt nlogn)$ 用线段树 阅读全文
posted @ 2019-04-07 13:17 jrltx 阅读(268) 评论(0) 推荐(0)
摘要:题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树。当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组。树的结点数可以用并查集来维护。总复杂度$O(nlog^2n)$。 阅读全文
posted @ 2019-03-27 13:37 jrltx 阅读(225) 评论(0) 推荐(0)