
数据结构
TeJoy
这个作者很懒,什么都没留下…
展开
-
bzoj3236 (莫队+分块)
bzoj3236 (莫队+分块)题意:nnn个数,mmm个询问,每次两个询问[a,b]值域数量[a,b]值域数值的数量思路:第一个询问乱做,第二个询问若没有值域要求莫队可解,带上值域要求莫队加树状数组可做,但是复杂度是O(nm)lognO(n\sqrt m)lognO(nm)logn洛谷的数据或许可以卡过去,但是bzoj上强化显然不可以,我们考虑这个问题的瓶颈,在于单点插入,区间查询都是O(logn)O(logn)O(logn)的,区间查询的复杂度可以更劣,我们考虑块状数组,能够做到O(原创 2021-05-24 20:38:33 · 361 阅读 · 1 评论 -
洛谷P4278 带插入区间k小值(值域分块+块状链表
洛谷P4278 带插入区间k小值(值域分块+块状链表题意:给一个序列,三种操作,强制在线1.区间k小2.单点修改3.单点插入思路:一道非常恶心的题…首先树套树能做1、2,但是单点插入不好维护,而且树套树太难写了。考虑分块k小首先kkk小怎么做?和线段树一样,值域分块根号n叉树,记录每个数出现次数和每个块的次数,在三层的根号n叉树上查找O(n)O(\sqrt n)O(n)即可解决区间k小那区间kkk小呢?再考虑序列分块,我们希望整块的信息O(1)O(1)O(1)获取,散块O(n原创 2021-05-08 10:01:45 · 407 阅读 · 1 评论 -
CC Chef and Churu(分块
CC Chef and Churu(分块题意:给一个长度为nnn的序列和mmm个区间两种操作1.单点修改2.维护第x个区间到第y个区间的和思路:先考虑暴力做,单独维护每个区间的和,这样的话总复杂度是O(Qm)O(Qm)O(Qm)的无法接受,复杂度的瓶颈在于每次都要所有区间一次,考虑对区间分块。所以我们要迅速知道某数的贡献,cnt[i][j]cnt[i][j]cnt[i][j]表示第iii块中jjj这个位置出现的次数。可以事先差分+前缀和预处理出cnt[i][j]cnt[i][j]cnt[i][原创 2021-05-07 23:42:43 · 326 阅读 · 0 评论 -
P4168 (静态分块
P4168 (静态分块题意:区间众数,强制在线思路:离线考虑莫队,在线考虑静态分块。块之间的贡献不独立,ans[i][j]ans[i][j]ans[i][j]表示块[i,j][i,j][i,j]中的众数,mx[i][j]mx[i][j]mx[i][j]表示众数的出现次数,通过增量法求解,O(n2/B)O(n^2/B)O(n2/B)考虑块与块之间的影响,用cnt[i][j]cnt[i][j]cnt[i][j]表示前iii个块中jjj的出现次数查询用散块暴力更新看是否对整块的答案有所贡献即可 $O(原创 2021-05-07 23:15:52 · 200 阅读 · 0 评论 -
洛谷P4135作诗(静态分块
洛谷P4135作诗(静态分块题意:查询区间内出现偶数次的数的个数,强制在线,值域O(n)O(n)O(n)思路:假如不强制在线的莫队板子题,但是强制在线怎么办呢,此时我们考虑静态分块,即不带修,放一些关键点,预处理关键点到关键点的信息来加速查询。显然块之间的贡献不是独立的,对于这种问题,我们一般直接预处理所有对应块的答案,然后考虑散块、整块之间的贡献。我们考虑f[l][r]f[l][r]f[l][r]表示从块l到块r的答案个数。可以直接通过增量法计算(枚举最左端的块l,再一直扫到n),复杂度O(n2/原创 2021-05-06 23:23:38 · 133 阅读 · 0 评论 -
loj 6546 (分块+斜率优化
loj 6546 (分块+斜率优化题意:给两个长度为n的数列A,B,三个操作对A区间加交换B中的两个数求区间最大Ai∗Bi{A_i*B_i}Ai∗Bi思路:看起来很像一道线段树,但我们发现区间加后根本难以维护Ai∗BiA_i*B_iAi∗Bi,对应的BiB_iBi不同,难以维护最值所以序列考虑分块,但仍然有点麻烦,认真考虑答案www如何计算www=add[i]∗b[i]+b[i]∗a[i]add[i]*b[i]+b[i]*a[i]add[i]∗b[i]+b[i]∗a[i],本原创 2021-05-06 22:42:49 · 254 阅读 · 0 评论 -
bzoj 2002(分块)
bzoj 2002(分块)转化后的题意:给n个点,组成很多森林,每个点和父亲相连,父亲的编号比儿子大,两个操作1.断掉某个点和父亲相连的边,将整颗子树接到另一个编号比他大的点2.求i点在所在树的深度,根深度为1这是很典型的树上问题,可以用LCT解决,这里我这样转化只是为了提醒自己以后遇到类似模型的时候可以尝试往序列分块上想,考虑转为序列问题,减少码量思路:假如没有断边接边操作,容易想到O(n)O(n)O(n)解法,考虑每次修改都暴力更新所有前面的点的答案,O(n)O(n)O(n)更新O(1)O原创 2021-05-06 21:29:11 · 189 阅读 · 0 评论 -
P5356 YNOI2017 由乃打扑克 (分块
P5356 YNOI2017 由乃打扑克题意:区间加,区间第k大数思路:主席树又无法维护,考虑数列分块区间查询显然数列分块后直接统计答案的话,块的贡献是不独立且不正确的,一个块的kkk小值不一定是另一个块内kkk小值,线段树上求kkk小本质是利用二分统计个数。所以我们也考虑二分答案,统计所有块小于等于该数的总数有多少个,假如小于k的话,二分的答案太小了,否则太大了。这样的话查询是O(logw(n/B∗logB+B))O(logw(n/B*logB+B))O(logw(n/B∗logB+B)原创 2021-05-06 20:43:42 · 4111 阅读 · 0 评论 -
洛谷P2801 分块
洛谷P2801 分块题意:区间加,查区间>=kkk的数的个数思路:区间大于等于k容易想到主席树,但是区间加,也无法标记永久化,所以难以维护。考虑数列分块区间查询这里块贡献仍然独立,考虑块内维护有序序列,整块可以一次二分得到答案,散块暴力即可O(n/B∗logB+B)O(n/B*logB+B)O(n/B∗logB+B)区间加对于整块,直接打addaddadd标记即可,散块的话,暴力做,可以选O(BlogB)O(BlogB)O(BlogB)重构有序序列,但实际上我们发现可以通过记原创 2021-05-06 20:16:18 · 201 阅读 · 0 评论 -
洛谷P3372 (分块)
洛谷P3372 (分块)题意:区间加,区间和思路:线段树板子,但拿来练分块。数列分块,显然块与块之间的贡献是独立的,所以可以看成是三层的根号n叉树。区间加散块暴力加,同时更新区间和(类pushUp),整块直接打加法标记区间查询散块直接暴力算,整块答案=add[i]∗len[i]+sum[i]add[i]*len[i]+sum[i]add[i]∗len[i]+sum[i]复杂度为O(n/B+B)O(n/B+B)O(n/B+B),块大小等于n\sqrt{n}n的时候复杂度最优#原创 2021-05-06 19:46:14 · 288 阅读 · 0 评论 -
bzoj1095(点分治+堆)
bzoj1095(点分治+堆)题意:给一堆点,一开始全为黑点,每次取反一个点,问树上最远黑点距离思路:考虑建立点分树维护全局答案,显然对于分治重心来说,我们只用考虑子树对应最长链和次长链,由于要能删除,所以用两个堆组成可删堆来维护,一个维护当前点子树节点对父亲的贡献,一个维护所有儿子的前一个的最大值,再用一个全局堆维护,修改挺多细节的,自己当端点的情况得考虑,0也得考虑,具体看代码吧,只能说这题太阴间了维护起来,直接存份板子了,另外如果把优先队列换成pbds里面的二叉堆可以快一半,直接过了洛谷最后原创 2021-04-16 15:43:46 · 126 阅读 · 0 评论 -
cf293 E(点分治+树状数组)
cf293 E(点分治+树状数组)题意:统计边数<=L且边权重<=w的路径数思路:显然用容斥点分解决,按照w排序后是单调的,然后用树状数组维护l的数量即可,时间复杂度O(nlog2n)O(nlog^2n)O(nlog2n)#include<bits/stdc++.h>#define fi first #define se second using namespace std;typedef long long ll;typedef pair<ll,int&g原创 2021-04-15 11:16:33 · 186 阅读 · 0 评论 -
bzoj3730 (点分树
bzoj3730 (点分树题意:1.查询距离x点为k的点的权值和2.单点修改第x个点的权值强制在线思路:带修且多次询问距离某点建立点分树维护,每个点开两个树状数组,一个用于维护当前分治区域对自己的贡献,一个维护对父亲的贡献,更新和维护从当前点在点分树上条根即可注意计算的时候容斥,点分树的老套路了,算上本身后,减去当前对父亲的贡献,算上父亲自己的贡献,注意对于每个分治区域,树状数组的大小,一个是前一个分治子树的大小,一个是自己的分治子树的大小,为了方便,我都开成了上一次的大小,此外,树状数组需原创 2021-04-15 11:05:42 · 138 阅读 · 0 评论 -
libreoj 6145(点分树)
libreoj 6145(点分树)题意:给一你一颗树,多次询问某点到编号为[l,r]的最短距离思路:多次询问某点的连通块问题,显然点分树套路题点分树的题一般都是一个点维护2个数据结构,一个维护自己分治区域对自己的贡献,一个维护对父亲的贡献,这里直接暴力维护两颗线段树就好了,下标就是标号。时空间复杂度O(nlog2n)O(nlog^2n)O(nlog2n),所以数组要开大点,此外初始值记得标为INF这里有一个错误我要注意,欧拉序求LCA后,原树两点间的距离得额外求!!!!#include<原创 2021-04-15 10:11:05 · 125 阅读 · 0 评论 -
gym102452 (点分治)
gym102452 (点分治)题意:点有点权,问树上路径数使得路径点权能构成一个多边形思路:香港区域赛的一题,当时vp的时候还不会点分,现在会了根本就是煞笔题嘛…显然是问2∗mx<sum2*mx<sum2∗mx<sum的路径数,由于枚举子树的时候要分类讨论,所以我们用容斥方法计数,存下从分治重心出发的路径。按照mxmxmx排序后,固定最大值枚举,假设枚举的两条链分别为x1x1x1,x2x2x2,由于根算重了,则转化为 2∗mx<x1+x2−rt2*mx<x1+x2-原创 2021-04-15 09:35:04 · 187 阅读 · 0 评论 -
bzoj 4860 (点分治+线段树合并)
bzoj 4860 (点分治+线段树合并)题意:给你一颗树,边有颜色对应权值,连续段权值只算一遍,问边数在[l,r]之间的路径中,路径权值的最大值思路:树上路径问题,带边数限制。先考虑点分。求最值,采用点分第二种写法,逐一枚举子树合并一开始想着对每个颜色都开一颗线段树,查的时候再遍历前面的一遍显然这个做法是O(nlog2n)O(nlog^2n)O(nlog2n)的。能否避免再遍历呢?其实我们发现,我们只关心当前子树是否相同和不相同的两类颜色。可以通过排序当前子树颜色,颜色上形成偏序关系,就原创 2021-04-07 16:32:59 · 145 阅读 · 0 评论 -
长链剖分题集及总结
长链剖分题集及总结树剖中我们常用的是重链剖分,是用于解决树上两点路径上相关问题的利器,当然也可以用于解决一些子树问题。今天和大家聊的是另一种树剖,基于深度的剖分具体怎么剖就不讲了,下面稍微讲一下他的性质和应用一.链长和是O(n)二.任意一个点k次祖先y所在的长链长度≥\ge≥k三.从任意一个点向上跳长链≤n\leq \sqrt n≤n次应用1.O(nlogn)−O(1)求k次祖先O(nlogn)-O(1)求k次祖先O(nlogn)−O(1)求k次祖先本质上是利用性质二,维护每个长链顶端向下原创 2021-03-15 21:04:10 · 480 阅读 · 0 评论 -
hdu 6444 (gcd+单调队列好题)
题意:给出长度为n的数组,目标快乐值s,体力m,跳跃间隔ka[i]表示i这个点的快乐值,每花费一体力跳到(i+k)%n的位置上可以获得a[(i+k)%n]的快乐值,问要达到目标快乐值s,初始至少需要多少快乐值,实际上就是求花费m体力最多能获得多少快乐值思路:首先显然在一圈上相当于每次跳gcd(n,k),所以循环节长度为n/gcd(n,k),而我们的起点有gcd(n,k)的可能,我们记下每个起点的下跳跃一圈的前缀和sum,当sum<=0的时候,显然不能跳完一圈,所以求最大子段和即可,环形最大子段原创 2020-07-19 16:08:51 · 173 阅读 · 0 评论 -
hdu 3410
题意:n个数,对于每一个数找到它左边的第一个比他大和他之间的最大值,和他右边的第一个比他大的和他之间的最大值。比如 5 2 4 3 1, 5左边没有值那就是0, 2和5之间没有值也是0, 4左边就是2 其他起个也是类似。右边和左边的一样。思路:维护一个单调递减的栈,如果进来的时候<=当前的值,证明左边啥都看不到,是0,否则边弹出边更新#include<iostream>#include<cstdio>#include<cstring>usi原创 2020-07-17 09:26:48 · 182 阅读 · 0 评论 -
hdu 6319(单调队列思维题
题意:给一组数列,输出从左到右的最大值及i的异或和,以及最大值更新次数的异或和思路:最大值显然可以用单调队列来维护,但是最大值的更新次怎么办呢,容易想到倒序做一遍单调队列,队列中其实倒序存储着更新的最大值,所以队列的个数即是最大值的更新次数,单调队列的又一个应用,求最大值更新次数#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef long long原创 2020-07-17 08:09:06 · 156 阅读 · 0 评论 -
单调队列/单调栈 poj2823 poj3250 poj2559
这三道单调队列和单调栈的题比较经典,写在一起poj 2823题意:滑动窗口思路:单调队列板子题,直接维护就好了#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn=1e6+5;int a[maxn],qmax[maxn],qmin[maxn],h1,t1,h2,t2,ans1[maxn],ans2[maxn];int main(){原创 2020-07-16 21:15:30 · 121 阅读 · 0 评论 -
hdu 1506(单调栈
题意:求最大矩形并面积思路:网上说啥笛卡尔树,但我也不懂…首先容易发现递增情况的最大值,就是从当前矩形往右延伸到边界,当出现比当前要矮的矩形的时候,前面比他高的部分就没用了,等效于用当前矩形的高度加上前面的宽度的新矩形代替,所以我们可以维护一个单调递增栈大于就直接丢进来,小于栈顶的话,就依次弹出,边弹出边累计宽度更新面积,然后把一个高度为当前矩形宽度,宽度为累计宽度的新矩形入栈。防止扫描之后还有剩余,所以在增加一个a[n+1]=0的矩形//单调栈求平面上最大矩形并面积#include<i原创 2020-07-11 17:52:51 · 223 阅读 · 0 评论 -
hdu 4252(单调栈
题意:这道题的题意完全看不懂,看懂了就瞬秒了,简单来说,就是用尽可能少的矩形覆盖所有区域,这样的话其实只有矩形的高度会造成影响,和先前高度一样的可以并在一起做法:具体来说就是维护一个单调递增栈,大于或者空的且非0就直接丢进去,小于就一直弹栈同时计数,等于的因为可以并在一起直接不管,最后再全部弹出来计数一次就好了#include<iostream>#include<cstdio>#include<cstring>using namespace std;con原创 2020-07-11 15:52:27 · 172 阅读 · 0 评论 -
poj 2828 (线段树查询第k小+离线处理
题意:排队问题,每次把vali插到posi的位置,问最后的序列思路:如果顺着做的话,复杂度n^2无法接受,我们可以发现一个重要的性质,前面的数对后面的没有影响,后面插入的对前面有影响,所以倒序处理,每个插入的位置其实是在当前所有排位的第posi+1个空位的位置 这个很容易证明,在原有的左边插入,不会影响,在右边插入,会根据之前插入过的个数倒退,所以就是第posi+1个空位,线段树或者树状数组搞搞就好了#include<iostream>#include<cstdio>#i原创 2020-06-18 17:47:54 · 170 阅读 · 0 评论 -
hdu 1394 (最小逆序对 线段树
题意:给n个0到n-1的数,每次可以取一个放后面,求最小逆序对思路:求逆序对可以利用树状数组或者线段树元素出现的时间差来维护,这里由于n个数是0到n-1,所以每次更新就是加上原来的顺序对,减去逆序对,就是+n-1-2*a[i]#include<iostream>#include<cstdio>#include<cstring>#define lson p<<1,l,mid#define rson p<<1|1,mid+1,r#de原创 2020-06-18 15:50:58 · 213 阅读 · 0 评论 -
codeforces Edu65 F. Scalar Queries(树状数组/线段树维护区间贡献)
F. Scalar Queries题解:看了很久才看懂的一道题,首先不难化简到 f(l,r)为a[i]*他在[l,r]中的区间第几小**面对这种从区间到点的问题,如果很难考虑,应转化为从点转换到区间,考虑每个点的贡献,**首先,每个点的贡献是来自于其左边和右边某个比它小的数aj,ai与aj,同时包含他们的每个区间会使a[i]*sum[i]中的sum[i]+1,这样就成功把区间排序改变,变成...原创 2020-04-25 13:35:44 · 147 阅读 · 0 评论