线段树

线段树思维题

HDU 4614  Vases and Flowers  二分答案求位置

题意:有n个花瓶,初始里面都没有话,现在有二种操作1:op,x,y 表示从第x个花瓶起,遇到花瓶就插入花,当一朵花也没有插入的时候输出no,其它情况输出插入的第一朵花的位置和插入最后一朵花的位置;操作2:op,x,y表示将区间x,y的花瓶里面的花都丢弃;

思路:维护懒标记add,和区间和sum,当花瓶里面没有花时为1; 当操作1:当sum(x,y)==0输出no其它情况类似主席树求第k大查询第一朵花和最后一朵花(min(r,sum(x,y) ))的插入位置即可,我在查询位置的时候也用到了求区间和操作,看大佬都是用二分答案写的,比我写的方法简单一点,偷偷去学了一波,操作2就简单了;总复杂度为n*logn*logn;

Codeforces 380c Sereja and Brackets  分治思想

有关公式的计算

几乎是懒标记,pushdown,pushup的改变

区间合并

HDU 4553 约会安排

题意:一个人要和男生女生约会,约会的规则是当和一个男生约会时,选择空闲的时间,如果没有输出一个字符串,如果有就和这个男生约会,当和一个女生约会时,先选择一段空闲的时间,如果没有就可以无视和男生的约会,将和男生约会的时间都当成空闲 的时间,再选择一段时间出来,没被选的不影响以前的状态,如果这样还没有找到一段时间,就输出一段字符串;当有时间完成时输出那段时间的开始时间

还有一个操作就是将l,r区间的所有约会都去掉;

思路:区间合并的板子题目,维护懒标记 add -1  0,1,2  当为-1时为混合状态,当为0时为空闲时间,当为1时为和男生约会的时间,当为2时,为和女生约会的时间,然后就是板子了, 特别注意的是,就是0状态当要和女生约会时可以当1状态用,我就在这里wa了几发;0 0 0 1 当出现DN4时输出的是1  而不是NO

离散化

HDU  4325 Flowers

题意:给n个区间 将区间l,r加1  然后m次询问,问a[t]有多大;  l,r,t,<=1e9

思路:l,r,t都比较大,我们将它离散化  然后就是区间更新,单点查询,差分,树状树状,线段树都可以

CodeForces  915E Physical Education Lessons

题意:有一个1到n的区间,n<=1e9,q个询问q<=3e5,开始1到n区间初始值都是1,q次询问,每次询问有二个操作,1:将区间l,r变成0 2:将区间l,r变成1;然后输出1到n 1的个数;

思路:这个题目有二种思路 1:动态开点线段树 2:离散化+线段树;

动态开点:   空间复杂度为logn*(查询和更改区间的个数)   差不多k*logn*q;然后就是板子了,可以参照算法竞赛进阶指南的板子;

离散化:1,n 和左右端点肯定是要离散化的,但是当排序后二个相邻的端点的差大于1时还要插入一个l+1,r-1的线段;

假设为   1 5 6 8 10

建成线段树后为    (1,5)左右端点为(1,10)         (1,3)左右端点为(1,6)     (4,5)左右端点为(8,10)  (4,4)左右端点为(8,8)  假设全部为1 ,我要查询区间(1,8)   那么加上的区间为 (1,3)1,6      (4,4) 8,8   值为6+1等于7不等于8 所以  如果端点为 1 5 6 8 10 离散化后应该为

数组下标 1 2 3 4 5 6 7 8   

 左端点  1 2 5 6 7 8 9 10

右端点1  4 5 6 7 8 9 10   既在二个端点还有点时要插入一个线段

注意:  if(l<=node[i*2].r)update(i*2,l,r,v);    if(r>=node[i*2+1].l)update(i*2+1,l,r,v);应该这样更新

2019牛客暑期多校训练营(第七场)E Find the median

题意:有n个询问 l,r ;先将l到r这r-l+1个数加入到一个数组中,求这个数组的中位数;上次的数还留在数组中;l,r<=1e9;

思路:这个题目动态开点是过不去的,只能离散化,和上题离散化一样,查询时到查询到叶子节点时,要么那个叶子节点只有一个数,要么那个叶子节点的所有数的一样;求第k大;很容易想到第k大为   先计算每个数加了几次num=node[i].sum/(node[i].r-node[i].l+1);答案就是p[l].first+(k+num-1)/num-1;(p[l].first为这个叶子节点维持的左区间)

codeforces 817F MEX Queries

题意:有q个操作(1e5),操作分3种,1:l,r 中所有数变成1  2:l,r所有数变成0  3:取反  输出每次操作后第一个为0的位置

注意l,r为long long 范围,

思路:先离散化(板子),有二类操作 区间赋值(0,1),区间异或,维护二个标记  flag,rev flag=0表示区间值为0,flag为1表示区间值为1,flag为-1表示混合区间   rev为1表示区间要反转,当区间反转时,先判断flag是不是-1,如果不是-1 flag取反,如果是-1rev取反 ;pushdown先判断rev,在判断flag(前面保证了flag等于-1时,rev在操作,如果flag不等于-1了,一定是后面区间赋值了,所以pushdown时flag操作要在rev操作之后)

扫描线

poj 2482  Stars in Your Window

题意:给出n个星星的坐标,每个星星有一个亮度,给出一个矩形的长和宽,问矩形能包括的星星的最大亮度和(不包括边框)

思路:一个矩形能覆盖一个点x,y那么那个矩形的右上点成一个矩形区域,为(x,x+w,y,y+w),这个点的权值在那个矩形区域里面,那么题意转换成在一个平面求一个点,这个点的权值最大,容易发现这个点一定在矩形区域的边界上,我们以x坐标建线段树,那么那个点一定在   y=cc那条直线上,那么就可以用扫描线,因为题目星星不能在矩形边界上,可以将x+w-1这样就可以保证不会在x=cc那条线上,按y排序时,当y相等时先处理c为负数的情况,那么就能保证星星不在y=cc那条直线上(奖y+h-1也可以,但是排序也要分情况。。)然后就是线段树了;但是扫描线线段树有一个特点,就是懒标记不用pushdown,这个就需要思考怎么处理了;AC代码  https://paste.ubuntu.com/p/xt7K2jYwkh/

多颗/多维 线段树

code forces 240f  26颗线段树

题意:给一个长度为n的字符串,m次操作,每次操作给l,r;如果l,r中的重复重新排列不能组成回文则忽略这次操作,如果可以组成回文,则将l,r区间的字符重新排列成一个字典序最小的回文;m次操作后输出最后的结果;

思路:建立26颗线段树,每颗线段树维护相应的字符所在的区间,假设ab则第一颗线段树区间(1,1)为1,其它为0,第二颗线段树(2,2)为1其它为0,每次给出l,r求出区间l,r各个字符的总数,然后从小到大分配字符,当然不是一个一个的分配,而是区间分配假设a有8个,那么区间l,l+3都分配a,r-3,r都分配a这样区间更新,只要26次就能分配所有的字符,这个题目还有一个小技巧,就是add标记,这个题目有区间更新,肯定是要add标记的,但是,如果你开add[26][len*4]这样标记第i颗线段树节点j是0,还是1,那么就会超时,这是因为数组太大的原因,其实只要add[len*4]这样就好了add[i]表示以节点i的区间都是add[i]这样才不会超时。(也可能是我都代码写崩了吧,才超时)

HDU 1823 线段树套线段树

题意:二个操作:1在点x,y加一个值(如果原来x,y有值,取最大的)2:查询x1,y1到x2,y2的矩阵最大值;

思路:1:矩形线段树模板 2:线段树套线段树   。。。。。先学了第一种,然后超空间,然后就去学了第二种。。。。fan

贴个板子   https://paste.ubuntu.com/p/KyX9sSpJZY/ 

ææ¯å享å¾ç

 

 

势能线段树

需要满足所有的修改都会使势能单调下降 ,最后处于一个稳定的状态(区间的数几乎相同)最坏总时间复杂度不会n*lognlogn;

HDU 5306 Gorgeous Sequence

题意:给3个操作,1:求区间最大值,2:区间求和,0:将l,r中  大于t的数变成t,小于t的数不变;

思路:势能线段树板子题目,1,2和以前的线段树套路一样,势能线段树主要就是减枝;当t>=max时,肯定是不需要更改那个区间的,那么什么时候更改呢,这个题目要多维护一个最大值的数量,和次大值,当second<t&&t<maxx时,将maxx改成t,懒标记也可以去掉,pushdonw  当 max[i]<max[i*2]的时候pushdown,max的数量 用来跟新sum,pushup当然是计算节点i的sum,maxx,c,se。。。                 现在分析一下会不会超时,当t是l,r区间最小值时,在叶子节点才会更新,这次会运行n*logn次,但是当下一次更新时,这个区间都会 是一个值   当t是l,r区间最大值时,也最多运行几次就结束了;

注意如果这个题目维护最大,最小值来减枝是不行的假设最小值为1,最大值为1e9 然后每次t等于max-1,就会超时

贴个板子:https://paste.ubuntu.com/p/NnzggzcjMG/

bzoj 5312 冒险

题意:1,给出l,r,x,将序列l,r之间的所有数都 and x  2,给出l,r,x,将序列l,r之间的所有数都 or x 3,给出l,r,询问l,r之间的最大值

思路:

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值