数据结构
文章平均质量分 53
issue是fw
19 years old, struggling in life, chasing daydreams.
展开
-
牛客练习赛70 F.曲调(离线,思维,权值线段树)
LINK 不看题解完全想不到,写下思路缕一缕 (顺便福利以下大众) 对数组aaa做前缀和,那么每次只需要找到[l,r][l,r][l,r]内差值最小的两个数即可 但是这个也显然做不了,考虑对询问区间排序后按照rrr端点离线 顺序扫描每个iii 考虑和前面每个aqa_qaq的差值为abs(ai−aq)abs(a_i-a_q)abs(ai−aq),那么我可以更新所有左端点小于等于qqq的答案 这个只需要以左端点对区间排序,插入到线段树上即可区间取minminmin 每次取出右端点为iii的区间的答案原创 2021-06-30 16:27:16 · 223 阅读 · 0 评论 -
牛客练习赛85 D.数学家的迷题(bitset暴力)
LINK 由于所有质因子只有不超过100001000010000个 考虑压缩所有质因子为二进制,可以使用bitsetbitsetbitset来优化 这样就用线段树来维护区间bitsetbitsetbitset 总体复杂度为O(m∗log(n)∗1000064)O(m*log(n)*\frac{10000}{64})O(m∗log(n)∗6410000) 当然也可以手动把100001000010000个质因子分为10000/50=20010000/50=20010000/50=200组 维护两百颗线段树原创 2021-06-25 22:43:55 · 241 阅读 · 0 评论 -
Codeforces Round #727 (Div. 2) F. Strange Array(思维,线段树子段和)
LINK 题意 给定长度为nnn的数组aaa,对于每个aia_iai 选定一个l<=i<=rl<=i<=rl<=i<=r,把区间[l,r][l,r][l,r]排序,中位数是第(l+r+1)/2(l+r+1)/2(l+r+1)/2个数记作kkk 再记aia_iai在排序后的数字中是第fff个位置,那么代价是∣k−f∣|k-f|∣k−f∣ 求出最大值 考虑只查询位置iii的答案怎么做,若选定区间[l,r][l,r][l,r],那么aia_iai可能在中位数左边,也可能原创 2021-06-24 23:33:57 · 222 阅读 · 0 评论 -
牛客练习赛51 F.ABCBA(树上主席树维护子序列)
LINK 题意 nnn个点的一棵树,每个点包含一个大写字母 询问mmm次,每次问vvv到uuu路径组成的字符串中,串ABCBAABCBAABCBA的数量 对于每组询问l,rl,rl,r,若l,rl,rl,r不在一条链上,可以先找出他们的lcalcalca为xxx 可以拆分为(l,x)(l,x)(l,x)和(x,r)(x,r)(x,r)两条链计算答案,再合并起来 这样一来,我们需要维护一条链中ABCBAABCBAABCBA所有子串的数量 发现这个东西是可以用线段树维护的 而且在一条链上的话,可以用主席树对每原创 2021-06-24 17:21:15 · 245 阅读 · 0 评论 -
The Preliminary Contest for ICPC Asia Xuzhou 2019 I. query(主席树)
LINK 由于这是一个排列,所有所有可能的答案对不超过nln(n)nln(n)nln(n) 暴力预处理出来,然后考虑对每个位置rrr维护一颗权值线段树 线段树的叶子节点kkk维护的是kkk和[k+1,r][k+1,r][k+1,r]形成了多少答案对 那么考虑[1,i][1,i][1,i]和[1,i+1][1,i+1][1,i+1]的权值线段树,差异其实是比较小的 我们完全可以效仿主席树那样去继承前一颗权值线段树 然后询问的话,直接在[1,r][1,r][1,r]的权值线段树里找到[l,r][l,r][l,r原创 2021-06-24 15:08:05 · 201 阅读 · 0 评论 -
P2617 Dynamic Rankings(动态区间第k小)
LINK #include <bits/stdc++.h> using namespace std; const int maxn = 1e5+10; #define mid (l+r>>1) int n,m,li[maxn<<2],top,a[maxn]; struct p { int type,l,r,k; }q[maxn]; int sum[maxn<<9],ls[maxn<<9],rs[maxn<<9],id; int rt原创 2021-06-22 22:08:36 · 239 阅读 · 0 评论 -
The Preliminary Contest for ICPC Asia Nanjing 2019 F.Greedy Sequence(主席树上二分)
LINK Ⅰ.si,1=is_{i,1}=isi,1=i Ⅱ.si,j<=si,j−1s_{i,j}<=s_{i,j-1}si,j<=si,j−1 Ⅲ.si,js_{i,j}si,j在数组aaa中的位置是posjpos_jposj,那么∣posj−posj−1∣<=k|pos_j-pos_{j-1}|<=k∣posj−posj−1∣<=k Ⅳ.sis_isi应该在字典序上最大 Ⅴ.设此时sis_isi的长度为kkk,在后面补齐n−kn-kn−k个000原创 2021-06-22 19:00:15 · 219 阅读 · 0 评论 -
P3605 [USACO17JAN]Promotion Counting P (dsu+线段树)
LINK 太久没写题了,写道板子题愉悦一下身心~ 没什么要说的,就dsudsudsu,动态开点权值线段树记录一下每个权值有几个 #include <bits/stdc++.h> using namespace std; #define mid (l+r>>1) const int maxn = 4e5+10; const int inf = 2e9; int n,a[maxn],ans[maxn]; vector<int>vec[maxn]; int ls[maxn<原创 2021-06-18 11:39:02 · 242 阅读 · 0 评论 -
牛客练习赛81 D.小 Q 与树(点分治+容斥)
LINK nnn个点的树,点iii的点权是aia_iai 求∑u=1n∑v=1nmin(au,av)∗dis(u,v)\sum\limits_{u=1}^n\sum\limits_{v=1}^n\rm min(a_u,a_v)*dis(u,v)u=1∑nv=1∑nmin(au,av)∗dis(u,v) 树上路径问题,考虑点分治 找出重心uuu,然后计算所有通过点uuu的路径贡献 然后从原图中消去点uuu,然后对各个连通块进行同样的分治. 通过点uuu的路径贡献怎么算… 先爆搜出所有从uuu出发的原创 2021-06-04 16:30:13 · 234 阅读 · 0 评论 -
牛客练习赛81 D.小 Q 与树(树剖+套路)
LINK nnn个点的树,点iii的点权是aia_iai 求∑u=1n∑v=1nmin(au,av)∗dis(u,v)\sum\limits_{u=1}^n\sum\limits_{v=1}^n\rm min(a_u,a_v)*dis(u,v)u=1∑nv=1∑nmin(au,av)∗dis(u,v) 考虑min\minmin不太好处理,我们按照点权从大到小加入 权值第iii大的点记作rki\rm rk_irki 那么这个点和前面所有点产生的贡献是 ∑i=1k(deeprkk+deeprki原创 2021-06-04 15:33:14 · 287 阅读 · 0 评论 -
2020ICPC 昆明 M.Stone Games(思维+可持久化线段树)
LINK 题意 给出长度为nnn的数组aaa和qqq次询问,每次给出区间[l,r][l,r][l,r] 你可以用区间[l,r][l,r][l,r]的任意子集来凑数,问最小的不能凑到的数是多少 其实有点像010101背包问题,但显然不符合时间复杂度 考虑区间[l,r][l,r][l,r]内没有数字111,那么答案就是111 否则设我们拥有xxx个数字111,毫无疑问可以凑出[1,x][1,x][1,x] 设kkk是继数字111后最小的数字,若存在k>x+1k>x+1k>x+1 显然x+1x原创 2021-06-01 15:39:09 · 369 阅读 · 0 评论 -
L. Lookup Performance(二分+主席树)
LINK 给定一颗二叉搜索树 qqq次询问给定区间[l,r][l,r][l,r],问从根节点执行lookup(1,l,r)lookup(1,l,r)lookup(1,l,r)函数共执行多少次 设节点xxx中权值最小权值为mixmi_xmix,最大的为mxxmx_xmxx 如果能访问到节点xxx,说明xxx的父节点rrr一定 ①.不满足L<=mir&&mxr<=RL<=mi_r\&\&mx_r<=RL<=mir&&mxr&原创 2021-05-27 12:20:14 · 271 阅读 · 0 评论 -
P2178 [NOI2015] 品酒大会(SAM后缀树)
LINK 对反串建立SAMSAMSAM,建立后缀树 树上有一些节点的初始siz=1siz=1siz=1,这些节点是反串的前缀,也就是原串的后缀 如果一个节点子树中的siz>=2siz>=2siz>=2说明这个节点可以作为lcplcplcp,lcplcplcp的值就是自己的longestlongestlongest 这样一来我们就可以树型dpdpdp,统计自己的sizsizsiz和,枚举儿子动态算贡献 只需要记录每个节点子树内的最大值和最小值即可 当然,如果不在遍历子树的时候顺便算贡献,就需原创 2021-03-06 19:59:58 · 251 阅读 · 0 评论 -
2020 CCPC Wannafly F.采蘑菇的克拉莉丝(轻重链的应用)
LINK 首先有一个很nativenativenative的想法 因为一个节点到父亲节点的边是容易统计贡献的,只需要算出不在子树内的蘑菇数量即可 现在只需要统计子树内蘑菇的贡献即可 当vvv节点加上xxx个蘑菇时,把根节点111到vvv的路径上都加上111 那么只需要枚举节点到所有儿子的边,就可以算了 这样会被菊花图卡掉 考虑优化 我们把vvv到根节点111路径上的点都加上xxx时,不断从重链跳到另一条重链去 所以,我们就把重链和重链间的那条轻边统计答案到它的父亲去 这样一来,途中的所有轻儿子的贡献都被累加原创 2021-03-06 19:13:38 · 251 阅读 · 2 评论 -
牛客练习赛73 D.离别(尺取+离线线段树)
传送门 考虑以每个iii为左端点,预处理右端点的合法区间为[li,ri][l_i,r_i][li,ri] 预处理的话只需要尺取就好了,因为处理lil_ili只需要处理到刚好有数等于kkk次 处理rir_iri就是刚好有数等于k+1k+1k+1次,此时下标减去一即可 那么现在离线询问,按照左端点大到小排序 一开始pos=npos=npos=n 然后每次让pospospos左移动到当前询问左端点的位置 每移动到一个位置,就把那个点的合法右端点[li,ri][l_i,r_i][li,ri]加入线段树原创 2021-02-09 12:57:48 · 197 阅读 · 0 评论 -
牛客练习赛9 E.子串(转移+扫描线+树状数组)
传送门 感觉非常不好写,我果然讨厌数据结构 预处理l[i]l[i]l[i]表示左边第一个大于iii的下标加一 预处理r[i]r[i]r[i]表示右边第一个小于iii的下标减一 转移方程是 for(int i=1;i<=n;i++)//作为右端点时,找左边第一个比i大的数字 { l[i] = i; if( p[i]>i ) continue; while( l[i]>1&&p[l[i]-1]<=i ) l[i] = l[l[i]-1];//我比左边的数字大,那么原创 2021-02-08 18:39:49 · 235 阅读 · 0 评论 -
P1972 [SDOI2009]HH的项链(主席树)
传送门 主席树做法 创建nnn棵线段树,第iii棵线段树维护[1,i][1,i][1,i]中每个数出现的最右边位置 那么查询[l,r][l,r][l,r]区间时,就去第rrr棵线段树上找左右大于等于lll的值即可 #include <bits/stdc++.h> using namespace std; #define mid (l+r>>1) const int maxn = 5e5+10; int n,id,a[maxn<<1],last[maxn<<1]原创 2021-02-06 21:42:30 · 278 阅读 · 0 评论 -
2021年牛客寒假集训营第三场 E.买礼物(链表+线段树(或主席树))
传送门 主席树做法待补 使用链表存储同种礼物所在的位置 nxt[i]nxt[i]nxt[i]表示下一个最近的和aia_iai相同礼物的位置 last[i]last[i]last[i]表示上一个最近的和aia_iai相同礼物的位置 然后在修改时动态维护链表 线段树维护nxt[]nxt[]nxt[]的区间最小值 于是[l,r][l,r][l,r]内查询nxtnxtnxt的最小值看是否小于等于rrr就好了 #include <bits/stdc++.h> using namespace std;原创 2021-02-06 09:13:32 · 255 阅读 · 0 评论 -
P3224 [HNOI2012]永无乡(线段树合并)
传送门 个人认为码风还是比较整洁的(作为线段树合并的代码,虽然常数巨大) 作为一个题一AAA题,还是非常愉悦的hhh 其实做法也比较显然 因为需要动态找到排名第kkk重要的 我们对每个点都维护一个权值线段树 然后并查集合并连通块的时候也顺便合并连通块 并且一定要合并到祖先的那个点上去 然后查询的时候,找到那个点的祖先,就算代表这个连通块的线段树 在树上二分查找即可 #include <bits/stdc++.h> using namespace std; #define mid (l+r>原创 2021-02-04 15:01:56 · 250 阅读 · 0 评论 -
P3714 [BJOI2017]树的难题(点分治+线段树合并)
传送门 这题做的我晕乎乎的,下次再来仔细理解 主要想法是找重心点分治,搜索出从重心开始的所有路径 如何合并路径是关键 对于长度为lenlenlen的路径,我们需要找到路径长在[l−len,r−len][l-len,r-len][l−len,r−len]中路径的最大值 但是简单的合并就好了吗?? 不是的,如果两条路径的连接处颜色相同,还需要减掉一次这种颜色的贡献 那么我们把重心的儿子存下来,按照颜色大小排序,依次搜索 这样相同的颜色路径是集中在一起被处理的 我们维护两颗线段树,都是以路径长度为下标 第一颗存与原创 2021-02-03 11:20:29 · 316 阅读 · 1 评论 -
817 F. MEX Queries(线段树区间赋值+取反)
传送门 离散化询问,建立线段树 维护两个标记tagtagtag表示当前区间赋值为0/10/10/1 revrevrev表示当前区间是否需要取反0/10/10/1 pushdownpushdownpushdown的时候首先看tagtagtag标记,有tagtagtag标记直接抹除所有revrevrev标记 再看revrevrev标记,把区间取反即可 #include <bits/stdc++.h> using namespace std; #define int long long #define原创 2021-02-01 16:25:21 · 402 阅读 · 0 评论 -
CF915E Physical Education Lessons(动态开点)
传送门 套个权值线段树就是裸题了 动态开点维护一个lazlazlaz标记表示当前区间的状态即可 #include <bits/stdc++.h> using namespace std; const int maxn = 15000005; #define mid (l+r>>1) int n,q,laz[maxn],ls[maxn],rs[maxn],sum[maxn],id,root; void pushdown(int rt,int l,int r) { if( laz[rt原创 2021-01-31 15:42:56 · 240 阅读 · 0 评论 -
P5459 [BJOI2016]回转寿司(动态开点)
传送门 求R>=pre[r]−pre[l−1]>=LR>=pre[r]-pre[l-1]>=LR>=pre[r]−pre[l−1]>=L 就是pre[r]−R<=pre[l−1]<=pre[r]−Lpre[r]-R<=pre[l-1]<=pre[r]-Lpre[r]−R<=pre[l−1]<=pre[r]−L 也就是把每个i∈[1,n]i\in[1,n]i∈[1,n]作为pre[r]pre[r]pre[r] 去[0,i−1][0,i-1原创 2021-01-31 15:14:20 · 295 阅读 · 0 评论 -
牛客练习赛3 F-监视任务(贪心+线段树)
传送门 其实有一个比较显然的贪心 我们按照rrr从小到大排序 第一个区间的右端点最小,那么这kkk个哨兵肯定是贴这右端点往左放 考虑第二个区间,同样是往右端点往左防止,这样对右边的区间最容易产生贡献 这个过程用线段树来维护 携带一个参数kkk表示需要在[l,r][l,r][l,r]从rrr往左找kkk个空位放哨兵 然后优先填充右儿子,再去左儿子即可 看代码吧 #include <bits/stdc++.h> using namespace std; #define mid (l+r>>原创 2020-12-18 17:28:00 · 317 阅读 · 1 评论 -
P4315 月下“毛景树”(树剖模板)
月下毛景树 好久没到树剖了,还好一遍过了… 边权转点权就是把边的权值下放到深度较大的那个点 然后在树上区间修改的时候,是不能算lcalcalca的 而当x,yx,yx,y跳到一条链的时候就是lcalcalca 所以最后一次是update(id[x]+1,id[y])update(id[x]+1,id[y])update(id[x]+1,id[y]) 另外这里有覆盖操作和区间加操作 覆盖操作优先级最高,注意一下push_downpush\_downpush_down写法 void push_down(int原创 2020-10-20 16:02:39 · 276 阅读 · 0 评论 -
P2824 [HEOI2016/TJOI2016]排序(排序转01线段树)
排序 这这这魔鬼才想得出来吧!!! 假如对每个操作排序一遍复杂度上天!! 但是区间排序能不能转换为线段树呢?? 可以的!! 如果值域只有0,10,10,1,就先查询区间内有多少111 升序排列,就是把后面的区间修改成111,前面修改成000 这题也是同理,由于询问只有一组,我们可以二分答案,转化为010101线段树 也就是二分某个值midmidmid,小于midmidmid的都变成000,否则变成111 这里注意一点,midmidmid并不是答案,只是企图从结果中缩小范围而已!! 对010101序列进行排序原创 2020-10-03 10:23:02 · 270 阅读 · 0 评论 -
P3979 遥远的国度(换根树剖)
遥远的国度 肯定不可能对每次换根重新树剖一次 那就是只以根111剖一次来换根 其中rootrootroot表示当前的根,uuu表示询问uuu子树内的最小值 分情况讨论 Ⅰ.若u==rootⅠ.若u==rootⅠ.若u==root,明显所输出a[1]a[1]a[1],全局最小值 Ⅱ.若u的深度大于root且u在1到root的链上,那么开始换根Ⅱ.若u的深度大于root且u在1到root的链上,那么开始换根Ⅱ.若u的深度大于root且u在1到root的链上,那么开始换根 此时我们找到在root到u的链上的v是u原创 2020-10-02 16:11:05 · 280 阅读 · 0 评论 -
P2184 贪婪大陆(转换思想->容斥)
贪婪大陆 很有意思的一题实际上是因为自己太水了… 很像线段树的题目,但一直找不到要维护的区间信息… 转变一下思想,不就是求区间[l,r][l,r][l,r]有多少不同的区间覆盖过吗? 如果区间[li,ri][l_i,r_i][li,ri]经过[l,r][l,r][l,r],满足li<=rl_i<=rli<=r 为此我们可以用树状数组维护lil_ili来统计 但是在这些区间内,如果ri<lr_i<lri<l也是不合法的 所有我们再开一颗树状数组来维护rir_iri原创 2020-10-02 13:59:04 · 254 阅读 · 0 评论 -
Poj2828 Buy Tickets(逆序思维+线段树)
POJ2828 题意 nnn个人,给你nnn次操作 第iii次操作表示编号pospospos的人插队到队伍第xxx个人后面了 问最后队伍的编号顺序 乍一看以为是链表裸题,但是发现查找第xxx个人会非常慢 结果题解十分巧妙 倒序考虑,因为最后面插入的人的位置是永远固定的 那么倒序考虑插入到第xxx个人后面说明前面要留刚好xxx个空位 这样我们把空位的值设为111,有人设置为000 那么倒序每次查找第x+1x+1x+1个空位就好了嘛~ 这样直接上线段树也很简单了(权值线段树) 如果去掉头文件等只有20行 #i原创 2020-10-02 10:34:53 · 406 阅读 · 0 评论