
线段树
穷源溯流
路很长,尽管走便是。
-
原创 Codeforces Round #698 (Div. 2) E. Nezzar and Binary String(思维+线段树)
给出两个长度为 n 的 01 字符串,给出 m 次操作,问 m 次操作过后是否可以将第一个字符串变为第二个字符串每次操作将 [l,r] 内的字符严格小于 (r-l+1) 的字符串反转,即 1 变为 0,0 变为 1,最多反转 (r-l) 个字符 如果没有严格小于区间长度一半的字符,那么这段字符将被丢弃题目说明两个字符串长度全为 n,所以只要长度不改变就好我们将第二个字符反向操作,看是否能将其变为第一个字符串,区间覆盖问题,利用线段树求解最后再一个一个进行询问...2021-01-31 22:53:0926
1
-
原创 洛谷 P3097 [USACO13DEC]Optimal Milking G(线段树+dp)
题目中的修改为基本操作,但是究竟要维护什么,值得我们去讨论其实很容易想到左端点到底要不要,如果左端点要是一种情况,左端点不要有是一种情况当选择左端点时,最优的时候是不是将奇数位置上的所有点都取,还是说中间要变,这便是我们熟悉的动态规划线段的每一个点都维护一个区间内部端点的选择情况 f[i][j] 当 i =0 时,表示左端点不取,j = 0 时,表示右端点不取这样在 push_up() 函数中应用动态规划即可const int N=4e4+5;#define int ...2021-01-19 10:08:3926
0
-
原创 洛谷 P2894 [USACO08FEB]Hotel G(端点线段树)
题目中更新操作为基本操作,查询操作比较难想查询时判断当前节点的左儿子是否满足有连续 x 的空位,或者左儿子与右儿子之间相连是否有连续 x 个空位 ,或者右儿子单独有 x 个连续的空位这样不禁令人想到一个题目 :https://baichuan.blog.csdn.net/article/details/110532388对于每一个节点维护该节点最长连续 sum 个空位 ,从左端点开始有 lsum 个空位,从右端点有 rsum 个空位这样查询操作就可以解决了const ...2021-01-17 14:59:1819
0
-
原创 洛谷 P7119 Mivik 的游戏(线段树)
这题模拟一下样例可以发现最后要求的是题目做的有点久了,就直接拿来用了(转载至 洛谷)其中 pi 是硬币反面的位置,k 是区间内硬币反面的个数const int N=1e6+5; int i,j,k; int n,m; //int a[N]; struct Node { int l,r; ll sum; //pi ll lazy,cnt; //cnt 为反面硬币数 ...2021-01-14 16:30:0929
0
-
原创 洛谷 P5889 跳树(线段树)
题目对于二叉树的知识点的考察直接拉满其实很容易发现对于只有 1,3 的序列是很容易维护的,但是同时要维护右儿子,需要清楚到底要维护什么设当前序列已经有 x 个有效的右儿子,(有效的意思是没有被访问父节点的操作抵消掉)那么其对答案的贡献值应该是剩下的就是找到有多少个有效的右儿子即可,由于这个序列会构成一棵树那么树的根,也就是深度最低的那个节点开始才记录有效的右儿子,不仅仅是右儿子,还有左儿子既然要维护树的根,不妨将维护这个序列转化为维护树的根,与树的右子树的深度...2020-12-19 13:12:5038
1
-
原创 洛谷 P5142 区间方差(线段树+数论)
关于求方差的题目之前做过,所以问题不算很难和这道题目很像:https://baichuan.blog.csdn.net/article/details/110707826区别是这道题目要用逆元求解,利用费马小定理预处理出前 n 个数的逆元即可解决问题const ll mod=1e9+7;const int N=1e5+5; int i,j,k; int n,m; ll a[N]; struct Node { int ...2020-12-19 08:47:5041
1
-
原创 洛谷 P4879 ycz的妹子(线段树)
题目有几处描述的不太准确,以至于以为是模板题D 的时候表示的是第 x 个有妹子的城市,而不是第 x 个城市好吧,做题的时候没注意到,剩下的就简单了,只有 D 操作和普通的线段树有所不同const int N=5e5+5; int i,j,k; int n,m; int a[N]; struct Node { int l,r; ll sum; int cnt; #defin...2020-12-14 23:10:2250
0
-
原创 洛谷 P2073 送花(权值线段树)
这个题如果要用线段树的话首先要考虑如何建树,那一定是动态开点了而且要维护最大值最小值,但是最气人的是有删点操作,所以在添加的时候要判断是否有节点为空。最后还有一个条件,相同的价格还不允许重新加入,看到这里应该要换思路了既然满足不重复的条件,想到之前有道 multiset 的题,题目用权值线段树解决删点时向区间最左或最右靠拢即可,添加时判断点是否早已存在const int N=1e6+5; int i,j,k; int n,m; //int a[...2020-12-14 09:14:3027
1
-
原创 洛谷 P1558 色板游戏(线段树+位运算)
由于 T 不超过 30 ,所以根据位运算,每一位代表一种颜色,利用在线段树上的或操作即可求得有多少个 1,统计 1 的个数即可注意 1<<(k-1) 代表的是二进制的第 k 位const int N=1e5+5; int i,j,k; int n,m; int a[N]; struct Node { int l,r; int sum,lazy; void update(int val)...2020-12-10 21:47:1931
0
-
原创 洛谷 P1471 方差(线段树+数学)
对于操作 1,2 应该很简单可以实现,但是操作 3,该如何实现,一定是要经过转化的,利用线段树,很容易求得任意区间的和,现在只剩下求 这一块的值为多少即可emmmmm,以我现在的数学能力是没有办法在化简了,但是我们可以用线段树再来维护一下这个值当区间 +k 操作时,那么有 这样区间平方和也变得可以维护了const int N=1e5+5; int i,j,k; int n,m; double a[N]; struc...2020-12-05 19:01:06112
0
-
原创 洛谷 P1438 无聊的数列(线段树+差分)
一开始的时候也是没有思路,但是看到了考点里有差分对于区间更新:对 l 位置 +k 对区间 [l+1,r] +d 对 r+1 位置 -(k+(r-l)*d)那么单点查询变成了a[p]+sum[p](sum[p] 为差分的前缀和)当然要注意,在更新区间时,要判断 l+1 与 r 的大小关系,以及对 r+1 位置的更新时,可能涉及到第 n+1 个数,所以在建树过程中不妨多开一个点以下代码无建树过程,因为初始差分值为 0const int N=1e5+5;...2020-12-05 08:58:54102
0
-
原创 洛谷 P3801 红色的幻想乡(线段树+容斥)
如果会二维线段树的话,这个题目应该会好想一点,但是数据范围不允许使用如果考虑一维线段树的话,只能考虑每次的贡献值其实不难发现,我们建两个线段树,分别维护 x 轴和 y 轴,这样对于每一次询问,只要找到 [x1,x2] 有几个标记的点(记为 x),[y1,y2] 有几个标记的点(记为 y)所以答案为,但是还差点,因为其所在的位置并没有红雾,而在计算横向有多少点和纵向有多少点时,都需要减去这个特殊点也就是减去,但是还有问题,这是一般情况,如果有两条直线重合呢?假设与 x 同向的...2020-12-03 17:31:51100
0
-
原创 洛谷 P6812 「MCOI-02」Ancestor 先辈(线段树+差分)
题意不大清楚,不过就是判断所给区间 [l,r] 是否是个单调递增(非严格)序列判断区间 [l,r] 是否是一个单调递增序列,可得任意一个数 a[i]-a[i-1]>=0 所以考虑差分设 d[i] 为 a[i] 的差分数组,所以题目转化成要判断 (l,r] 区间上的差分数组 d 的最小值大于 0而且题目涉及区间更新,所以用树状数组,但是树状数组我不会怎么更新区间最小值所以题目成了线段树裸题,分块也应该可以const int N=1e6+5; int i,...2020-12-03 16:18:0862
0
-
原创 洛谷 P6492 [COCI2010-2011#6] STEP(端点线段树)
其实这个题直接模拟即可,也算是要记住的一个模板了对于线段树维护的每一个区间,都有一个区间最值 maxx,左端点前缀,以及右端点后缀当更新一个点时,每次 push_up 都要做到从子节点转移到本节点,还要为其父节点的更新做铺垫所以对于任意一个节点 x 来说x 的左前缀是其左儿子的左前缀,x 的右后缀为其右儿子的右后缀,区间最值为其左右儿子的最大值但是当端点处更新时,我们要判断连接处是否更大,以及为父节点考虑如果 x 是父节点的左区间,那么判断 x 的左前缀是否要更新如果 ...2020-12-03 15:18:20112
0
-
原创 洛谷 P3611 [USACO17JAN]Cow Dance Show S(线段树+二分)
//#pragma GCC optimize(2)#include <bits/stdc++.h>#include <iostream>#include <cmath>#include <cstdio>#include <algorithm>#include <cstring>#include <queue>#include <vector>#include <utility>#.2020-11-29 17:03:0565
0
-
原创 洛谷 P2574 XOR的艺术(线段树)
const int N=2e5+5; int i,j,k; int n,m; int a[N]; struct Node { int l,r; int lazy; int sum; void update() { lazy^=1; sum=(r-l+1)-sum; } }t[N<<2];...2020-11-28 11:16:5050
0
-
原创 洛谷 P1637 三元上升子序列(权值线段树+离散化)
和求逆序对的题目差不多,还是按照桶排的思想,将线段树上的每一个点映射到对应位置,然后动态加点,统计每个数 a[j] 之前有多少个 a[i] 满足题目要求,将线段树清空后,再从后遍历一遍数组,寻找 满足 a[k] 的个数,根据乘法原理,两边求得的数相乘即可得到答案,当然对数据需要离散化才可以,用树状数组的话码量会小一点const int N=3e4+5; int i,j,k; int n,m,t; ll a[N]; vector <ll> v...2020-11-27 19:31:4662
0
-
原创 洛谷 P1774 最接近神的人(权值线段树+离散化)
根据贪心,每次都要交换两个逆序对,所以这个题目就是求逆序对的个数利用权值线段树来动态加点,每次询问找区间内 [id+1,n] 的所有数的个数,由于取值线段树本身具有顺序,所以可以将区间查询变为单点查询最后注意输出一定要 printf("%lld\n") ( 用 I64 错都不知道怎么错的)const int N=5e5+5; int i,j,k; int n,m,t; ll a[N]; struct Node { int l...2020-11-26 13:18:0748
0
-
原创 2020 ICPC Data Structure Problem(前缀和+线段树)
给出 2n 个数分别代表 a b 两个数组,题目要求维护数 c,c 是由 a,b 递推过来的题目的难点在于如何将单点修改转化到区间上来,我们可以枚举一下 ci 来寻找规律c1=max( a1,b1 ) c2=max( a2,max(b1+b2,a1+b2) ) c3=max( a3,max(a2+b3,max(b1+b2+b3,a1+b2+b3) ) ) 由此可以得出#define inf (1e18+1ll)const int N=2e5+5;...2020-11-19 22:29:5132
0
-
原创 Educational Codeforces Round 87 (Rated for Div. 2) D. Multiset(线段树)
输入 n,m ,代表有 n 个数,m 次更新输入 n 个数 ,将这 n 个数放入多重集合中,m 次更新,输入 kk<0 时,寻找序列中第 (-k) 个数,然后删除它 k>0 时,将值为 k 的数插入进去由于 a[] 数组的值 都不大于 n ,所有可以有桶排的思想得到,将每一个数映射到权值线段树上,当 k >0 时,直接插入,k<0 时,寻找第 (-k) 个元素,然后将权值减 1,但是这个题目内存卡的比较紧,线段树的节点包含的元素要尽量少con...2020-11-03 23:23:5424
0
-
原创 POJ 2528 Mayor‘s posters(线段树+离散化)
有 n 张海报,每张海报覆盖一段区间,后面的海报会覆盖前面的海报,求最后有多少张海报可以在墙上被看见(看见一点也算)const int N=1e5+5; int n,m,t; int i,j,k; //int a[N]; Pair p[N<<2]; vector<int> v; struct Node { int l,r; int flag;//被第几张海报覆盖 ...2020-10-11 07:53:3523
0
-
原创 A Simple Problem with Integers(区间修改+区间求和)
const int N=1e5+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l, r; ll sum,lazy; void update(int x) { sum+=1ll*(r-l+1)*x; lazy+=x; } }node[N<<2]; ...2020-09-29 22:32:0229
0
-
原创 HDU 1698 Just a Hook(lazy)
const int N=1e5+5; int n,m,t; int i,j,k; //int a[N]; struct Node { int l,r; int lazy; void update(int x) { lazy=x; } }node[N<<2];void build(int l,int r,int id){ ...2020-09-28 23:07:3323
0
-
原创 HDU 1754 I Hate It(区间查询+单点修改)
const int N=2e5+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l,r; int maxx; }node[N<<2];void push_up(int id){ node[id].maxx=max(node[id<<1].maxx,node[id<<1|1].maxx);}void bui...2020-09-28 21:58:0932
0
-
原创 1551:维护序列(区间乘法+区间加法)
虽然感觉是模板题,但做起来很不容易啊在对区间进行乘法运算 (假设 *k )时,乘法的 lazy 标记需要变为 lazy*k区间之和 sum 也要变为 sum*k但是要注意区间的加法运算标记 lazy(add) 也要 *k因为现有的 lazy(add) 标记还未加到区间中还应该注意的是在 lazy 标记的 push_down 操作中,应该先下放 乘法运算的 lazy 标记,因为在上面已经将 lazy(add) 更改了const int ...2020-09-20 09:13:3059
0
-
原创 1550:花神游历各国 (区间开方)
区间问题向 下放操作 上去考虑,当子节点全部都是 1 / 0 时,此时不需要操作更新const int N=1e6+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l, r; ll sum; bool f; //所有子节点都 <=1 则为 1 ; }node[N<<2]; void push_up(int...2020-09-19 11:13:4724
0
-
原创 1548:A Simple Problem with Integers
const int N=1e6+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l, r; ll sum,lazy; void update(int x) { sum+=1ll*(r-l+1)*x; lazy+=x; } }node[N<<2]; ...2020-09-19 09:07:3326
0
-
原创 P3368 【模板】树状数组 2(区间修改+单点查询)
const int N=1e5+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l,r; ll sum,lazy; void update(int x){ sum+=1ll*(r-l+1)*x; lazy+=x; } }node[N<<2];void push_up...2020-09-14 09:09:5132
0
-
原创 P3372 【模板】线段树 1(区间更新+区间求和)
const int N=1e5+5; int n,m,t; int i,j,k; int a[N]; struct Node { int l,r; ll sum,lazy; void update(int x){ //lazy 清空操作 sum+=1ll*(r-l+1)*x; lazy+=x; } }node[N<<2];...2020-09-14 09:02:5825
0
-
原创 P3374 【模板】树状数组 1(区间求和+单点修改)
const int limit=5e5;const int N=5e5+5; int n,m,t; int i,j,k; int a[N];struct node{ int l,r; int sum;}tree[N<<2];void build(int l,int r,int id){ tree[id].l=l,tree[id].r=r; if(l==r) tree[id].sum=a[l]; else{ ...2020-08-02 23:33:5446
0
-
原创 1549:最大数
const int limit=2e5;const int N=2e5+5; int n,m,t; int i,j,k; int a[N<<2];void build(int l,int r,int id){ if(l==r) return ; a[id]=-inf; int mid=l+1>>1; build(l,mid,id<<1); build(mid+1,r,id<<1...2020-08-02 21:44:02129
0
-
原创 1547:区间和 (线段树模板)
【输入样例】10 200 1 101 1 40 6 61 4 101 8 91 4 90 10 21 1 80 2 101 3 90 7 80 3 100 1 11 3 81 6 90 5 51 1 80 4 21 2 80 1 1【输出样例】1060616624145041const int N=1e5+5; int n,m,t; int i,j,k; ll sum[N*4];void b...2020-07-31 23:12:2286
0
-
转载 A Simple Problem with Integers(tag-lazy模板)
DescriptionYou haveNintegers,A1,A2, ... ,AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.Input...2020-06-08 16:50:07134
0
-
转载 2182:Lost Cows
DescriptionN (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their e2020-06-07 21:21:4370
0
-
原创 第14周训练总结----线段树
线段树是一种高效的查询区间,更新区间(例如:求某一区间的最值,与总和)的数据结构,以 log2N 的速度完虐暴力求解过程。线段树本质是一颗二叉树,每一个节点记录一个区间的信息,他的左儿子记录[L,(L+R)/2],右儿子记录区间[(L+R)/2+1,R]假设有一段区间长度为N ,分别为a[1],a[2],a[3],……a[N-1],a[N]线段树的实现:长度为n的数组struct tree{ int left,right; //记录题目所需要的 区间...2020-06-07 16:16:2571
0