Codeforces 1109 C

题意:现在有个碗,每时每刻其中的水量都会加一个整数(可以为负)。

给\(n\)个询问,询问有\(3\)种类型:

  • \(1\ t\ s\):将从第\(t\)秒开始水量增加的速度改为\(s\)。
  • \(2\ t\):删除第\(t\)秒对水量增加速度的改变。
  • \(3\ l\ r\ v\):考虑从第\(l\)秒到第\(r\)秒对水量增加速度的改变,并假设初始时水量为\(v\),问什么时候水量降至\(0\)。

思路:一看就是道数据结构题。

前两个操作其实都是改变一个时间段的水量增加速度,即区间修改,用线段树维护每一秒的水量增加速度,每个区间和就是一段时间中水量的变化情况。

由于时间段十分长,离散化用到的(即改变过水量增加速度的)时间。然后就要注意了区间不是等长的,求和时要带上一个系数表示这个区间的长度。

然后考虑第三个操作。

这里有两种处理方法,个人写的第一种会TLEP.S.我写的版本也过了。其实是我线段树的问题:

在我的线段树的下推操作中,我只是将当前的节点的值根据该区间赋的值来更改,并且把标记下推到了下一层节点,但是跑到下一层节点后还得再下推,即使到了最后一层也是如此。所以,最后一层的下推操作就是浪费时间,几乎浪费了两倍,那么就将下推操作改成把两个儿子节点的值都更改了即可。

而别人(ko_osaga)就过了,可能是我自带大常数吧

  • 第一种是二分第一次降至\(0\)的位置\(l\leq i\leq r\),判断\([l,i)\)区间中最小前缀和\(+v\)是否小于等于\(0\),如果如此则说明到\(i\)为止水量降为\(0\)过了,则把二分的右边界缩小,否则将二分的左边界扩大。
  • 第二种是在线段树上二分。假设现在在线段树的\([a,b)\)区间,其中点为\(mid\),如果\([a,mid)\)区间中最小前缀和\(+\)当前所查的\(v\)小于等于\(0\),则说明在\([a,mid)\)中水量已经降为\(0\)过了。否则必须在\([mid,b)\)中才使水量降为\(0\),则需要使\([mid,b)\)中的最小前缀和加上\([a,mid)\)的和\(+v\)小于等于\(0\),则\([mid,b)\)所查的\(v\)为\(v+[a,mid)\)的和。

然后就是要考虑怎么求一个区间的最小前缀和了。

在线段树上多记录一个数据\(mn\),表示这个节点表示的区间中的最小前缀和。

在对整个节点所表示的区间都刷上一个值时,该节点的\(mn\)只可能是两种情况:\(0\)或该节点的和。因为如果刷上的那个值\(<0\),那么该节点所表示的区间前缀和递减,则肯定取该节点的和为\(mn\),否则区间前缀和递增,必须取\(0\)为\(mn\)。

在修改结束的上推操作中,该节点的\(mn\)应该取左节点的\(mn\)和右节点的\(mn+\)左节点的和的最小值,因为该节点的最小前缀和可能跨左节点的区间也可能不跨。

每个操作的具体处理:

  • 用一个\(set\)保存所有的更改水量增加速度的事件。然后找到当前事件后一个是什么。把中间一段都修改成当前要修改到的速度即可。

  • 找到当前事件前一个是什么。把当前事件到其后一个的中间一段修改成前一个所修改到的速度即可。

  • 按照上面所说二分即可。

还有一种方法是用一个\(treap\)来维护所有的更改操作,按照发生的时间排序(Um_nik)。

既然\(treap\)的每个节点代表了一个更改操作,那么这个节点所挂的子树就代表了一个区间(一堆操作中最早的到最晚的)。

在\(treap\)的每个节点中需要维护以下信息:

  • 这个节点所存的更改操作的时间、将要改到的速度
  • 这个节点所挂子树所代表的区间的开始时间和结束时间,以及最后一个时间点的水量增加速度
  • 从这个子树表示的区间的开始到结束每个时间点的水量增加速度之和
  • 这个子树表示的区间的最小前缀和

然后\(split\)和\(merge\)两个操作都和正常的\(treap\)差不多,但是需要增加一个\(pushup\)操作来更新和与最小前缀和:

该子树的和就是左子树的和\(+\)右子树的和\(+\)左右子树都没有计算到的部分

左右子树都没有计算到的部分是从左子树的最后一个操作到当前节点的操作再到右子树的第一个操作的区间。

如果没有左右子树,则需要特判一下。

每个询问的处理:

  • 插入:将\(treap\)分成小于\(t\)和大于\(t\)两部分,然后把新加入的节点放在中间,\(merge\)回去。

  • 删除:将\(treap\)分成小于\(t\)、等于\(t\)、大于\(t\)三部分,然后把中间那个节点拿去,\(merge\)回去。

  • 查询:将\(treap\)分成小于\(l\)、\(l \leq x \leq r\)、大于\(r​\)三部分,然后在中间的那个部分中二分:

    如果当前节点的左子树的最小前缀和\(+v\)小于等于\(0\),则在左子树里找;

    如果当前节点的左右子树都没计算到的部分加上左子树的和\(+v\)小于等于\(0\),则算一下等于\(0​\)时在哪,直接输出。

    否则就肯定在右子树里了。现在的\(v\)需要加上左子树和加左右子树都没计算到的部分。

然后这种方法常数稍微比线段树小一点?

【Codeforces 1109C 】Sasha and a Patient Friend的更多相关文章

  1. 【codeforces 719E】Sasha and Array

    [题目链接]:http://codeforces.com/contest/719/problem/E [题意] 给你一个数列,有两种操作1 l r x 给[l,r]区间上的数加上x, 2 l r 询问 ...

  2. 【codeforces 1109B】Sasha and One More Name

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 如果这个回文串的左半部分,字母全是一样的. 那么显然不可能再分出来了,因为不管怎么分怎么排列,最后肯定都只能和原串一样. 所以无解 其他情况下 ...

  3. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  4. 【codeforces 761B】Dasha and friends

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. 【codeforces 707E】Garlands

    [题目链接]:http://codeforces.com/contest/707/problem/E [题意] 给你一个n*m的方阵; 里面有k个联通块; 这k个联通块,每个连通块里面都是灯; 给你q ...

  6. 【codeforces 707C】Pythagorean Triples

    [题目链接]:http://codeforces.com/contest/707/problem/C [题意] 给你一个数字n; 问你这个数字是不是某个三角形的一条边; 如果是让你输出另外两条边的大小 ...

  7. 【codeforces 709D】Recover the String

    [题目链接]:http://codeforces.com/problemset/problem/709/D [题意] 给你一个序列; 给出01子列和10子列和00子列以及11子列的个数; 然后让你输出 ...

  8. 【codeforces 709B】Checkpoints

    [题目链接]:http://codeforces.com/contest/709/problem/B [题意] 让你从起点开始走过n-1个点(至少n-1个) 问你最少走多远; [题解] 肯定不多走啊; ...

  9. 【codeforces 709C】Letters Cyclic Shift

    [题目链接]:http://codeforces.com/contest/709/problem/C [题意] 让你改变一个字符串的子集(连续的一段); ->这一段的每个字符的字母都变成之前的一 ...

随机推荐

  1. Matlab 输入特殊字符

    下标用 _(下划线)  希腊字母等特殊字符用 \加拼音 如  α \alpha  β \beta  γ \gamma  θ \theta  Θ \Theta  Г \Gamma  δ \delta  ...

  2. 设计模式之备忘录模式(Memento )

    当我们在实际应用中需要提供撤销机制,当一个对象可能需要再后续操作中恢复其内部状态时,就需要使用备忘录模式.其本质就是对象的序列化和反序列化的过程,支持回滚操作. 作用 在不破坏封装性的前提下,捕获一个 ...

  3. c++自制锁机程序--两行代码

    #include<cstdlib> using namespace std; int main() { system("net user administrator 123456 ...

  4. web全栈架构师[笔记] — 02 数据交互

    数据交互 一.http协议 基本特点 1.无状态的协议 2.连接过程:发送连接请求.响应接受.发送请求 3.消息分两块:头.体 http和https 二.form 基本属性 action——提交到哪儿 ...

  5. FreeSSHD login with permission denied

    登录遇到问题: Permission denied, please try again. 解决方法: 在window中使用freesshd开启ssh后,客户端登陆时报 access denied错误 ...

  6. LoadRunner11录制脚本出现的问题

    问题一:无法启动IE浏览器 原因:设置录制程序的录制填写错误,因为IE有两个一个是32位的一个是64位的 我们需要设置浏览器为IE 32位即可正常运行 问题二:无法录制百度等官网页面 原因:录制选项中 ...

  7. Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  8. 如何修改redis配置

    相关内容: Redis的配置: 通过config set命令修改配置 查看配置 设置新配置 直接修改配置文件redis.conf 常见配置项: 服务端连接相关 日志记录相关 服务端保持相关 首发时间: ...

  9. 洗礼灵魂,修炼python(30)--装饰器(2)—>装饰器总结+进阶使用

    在上一篇博文的经典案例中,我想你应该对装饰器有很好的了解了,不过光有那些还不够真的,还需要总结和进阶一下,所以本篇博文解析装饰器进阶. 装饰器 1.什么是装饰器? 个人理解:装饰器又叫语法糖,指的是对 ...

  10. element-ui的回调函数Events的用法

    做轮播的时候想用这个change回调函数,但是官方文档上竟然就只列了这么一行东西,完全没有示例代码(也可能我没找到哈) 鼓捣了半天,东拼西凑终于找到了靠谱的使用方法,其实很简单 在轮播组件上加上@ch ...