Codeforces I. Vessels(跳转标记)
题目描述:
Vessels
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There is a system of n vessels arranged one above the other as shown in the figure below. Assume that the vessels are numbered from 1 to n, in the order from the highest to the lowest, the volume of the i-th vessel is a**i liters.

Initially, all the vessels are empty. In some vessels water is poured. All the water that overflows from the i-th vessel goes to the (i + 1)-th one. The liquid that overflows from the n-th vessel spills on the floor.
Your task is to simulate pouring water into the vessels. To do this, you will need to handle two types of queries:
- Add x**i liters of water to the p**i-th vessel;
- Print the number of liters of water in the k**i-th vessel.
When you reply to the second request you can assume that all the water poured up to this point, has already overflown between the vessels.
Input
The first line contains integer n — the number of vessels (1 ≤ n ≤ 2·105). The second line contains n integers a1, a2, ..., a**n — the vessels' capacities (1 ≤ a**i ≤ 109). The vessels' capacities do not necessarily increase from the top vessels to the bottom ones (see the second sample). The third line contains integer m — the number of queries (1 ≤ m ≤ 2·105). Each of the next m lines contains the description of one query. The query of the first type is represented as "1 p**i x**i", the query of the second type is represented as "2 k**i" (1 ≤ p**i ≤ n, 1 ≤ x**i ≤ 109, 1 ≤ k**i ≤ n).
Output
For each query, print on a single line the number of liters of water in the corresponding vessel.
Examples
Input
Copy
25 1061 1 42 11 2 51 1 42 12 2
Output
Copy
4
5
8
Input
Copy
35 10 861 1 122 21 1 61 3 22 22 3
Output
Copy
7
10
5
思路:
这道题是让模拟一下水流的过程,不断操作,或者往一个槽子加水,或者询问某个槽子的水量。
首先一个最最朴实的想法是:建立数组模拟水流过程,若水满了,往下一个槽子流即可。但是在测试点8就回超时。显然还有优化的余地。
怎么优化呢?然后就开始了冥思苦想的过程,想到往一个槽子里的水加满后,实际上以后再往这个槽子里加水就可以忽略这个槽子了,不只是这个,由于槽子中的水不会减少,水流过程中的满的槽子均可以忽略。怎么实现呢?我首先想到了链表,不断可以摘除满的节点,从而使遍历更快捷。但是如果这样该怎么跟槽子的编号对应呢?比如我1到5号,其中3号已满,我删了之后以后如果再从3号倒水我怎么知道他该从哪个槽子开始倒呢?
又想了想前缀和。我们可以维护一个水流槽子的前缀和,比如样例1,有5,10,8,前缀和是5,15,23,只有当流过1的水流大于5才会流到2号槽子中,大于15才会流到3号槽子中,大于23才会往后面的槽子流。就累计一下从1开始流的总水量,下一次如果是从1开始流的话我们就立刻在1的前缀和中二分查找(单调性)到接下来该往哪个槽子流。这样一想,岂不是要维护2*10^5个前缀和,而且由于每次pour的起点不一样,维护操作可能会十分复杂。
其实最终的思路和思路一是一致的,区别在于实现上。实际上我们并不需要在物理上删除这个节点,只要在逻辑上跳过它就行了。我们建立一个nxt数组,来实现逻辑上的跳转。每次pour都把已满的槽子的nxt最终指向最近的未满槽子。那么每次再从满的槽子pour的时候不用一个一个遍历,而直接跳转到未满的下一个槽子了。
代码:
郁闷,非常郁闷,我把最终循环出来的起点设置为pour起点p的前面一个位置就一直T38,改为起点p就AC了。为什么嘞?因为啊,如果p出来是1,nxt[p]本来是2,nxt[p-1]=nxt[0],这个值没有意义,也没有设置过,就是默认的0,于是,t=nxt[0],循环里面nxt[0]=i;j=t=0;也就是一直都是t=0在无限循环,直到超时。我原先的想法是,既然p这个位置满了,那它之前的下次流出的时候的nxt也应该跳转,可以节省一次循环,但由于忘记考虑特殊的0点,(其实是考虑了,但是觉得没错,(:з」∠)),就陷入了死循环,如果把nxt[0]改为1应该就好了。注意考虑边界条件。
#include <iostream>
#include <cstdio>
#define max_n 200005
using namespace std;
int n,m;
long long a[max_n];
long long b[max_n];
long long nxt[max_n];
template <typename T>
inline void read(T& x)
{
x=0;int f = 0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=f?-x:x;
}
#pragma optimize(2)
int main()
{
read(n);
for(int i = 1; i<=n; i++)
{
read(a[i]);
nxt[i] = i+1;
}
nxt[n+1]=n+1;
read(m);
while(m--)
{
int st;
read(st);
switch(st)
{
case 1:
{
int p;
long long x;
read(p);
read(x);
int i;
long long sum = 0;
for(i = p; i<=n; i=nxt[i])
{
//cout << "x " << x << " i " << i << " a[i] " << a[i] << " b[i] " << b[i] << endl;
if(b[i]+x<=a[i])
{
b[i] += x;
break;
}
sum = x+b[i]-a[i];
b[i] = a[i];
x = sum;
}
int t;
if(a[i]==b[i])i=nxt[i];
for(int j = p; j<i; j=t)//p改为p-1就T了
{
t = nxt[j];
nxt[j] = i;
}
/*cout << "next ";
for(int i = 1;i<=n;i++)
{
cout << nxt[i] << " ";
}
cout << endl;*/
break;
}
case 2:
int k;
read(k);
printf("%I64d\n",b[k]);
break;
}
}
return 0;
}
参考文章:
码代码的猿猿的AC之路,CodeForces 371D. Vessels,https://blog.csdn.net/ck_boss/article/details/17249213
Codeforces I. Vessels(跳转标记)的更多相关文章
- CodeForces 371D. Vessels
暴力+胡乱优化就过了..tags给的东西似乎什么都没用到.....CF的数据是不是有点水啊.....果然是没有营养的题目..... D. Vessels time limit per test 2 s ...
- Military Problem CodeForces - 1006E(dfs搜一下 标记一下)
题意: 就是有一颗树 然后每次询问 父结点 的 第k个结点是不是他的子嗣...是的话就输出这个子嗣..不是 就输出-1 解析: 突然想到后缀数组的sa 和 x的用法..就是我们可以用一个id标记当前 ...
- Codeforces 371D Vessels (模拟)
题目链接 Vessels 这道题我做得有点稀里糊涂啊==TLE了几发之后改了一行就A了. 具体思路就是记fi为若第i个容器已经盛不下水了,那么接下来盛水的那个容器. hi为若现在要给i号容器加水,当前 ...
- Codeforces 444C 线段树 懒惰标记
前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记. 然后昨天真的是给这道题跪了,写了好久好久,...我本来是写了个add标 ...
- CodeForces 371D Vessels(树状数组)
树状数组,一个想法是当往p注水时,认为是其容量变小了,更新时二分枚举,注意一些优化. #include<cstdio> #include<iostream> #include& ...
- for或者while的标记循环
for或者while的标记循环 今天在写代码的时候,发现一个for循环前有一个字母,不知道这个是什么语法,后来查了一下,这个语法是用来实现标记循环的功能 这个是代码块 r:for(int rowNum ...
- springMVC源码分析--页面跳转RedirectView(三)
之前两篇博客springMVC源码分析--视图View(一)和springMVC源码分析--视图AbstractView和InternalResourceView(二)中我们已经简单的介绍了View相 ...
- gvim -- 跳转命令,查找格式,正则
1.跳转命令 ‘w'单词前进,'b'单词后退,'e'单词前进,‘ge’单词后退,存在单词词首词尾区别,'W''B''E''gE'将不以单词区分,以空格区分 ‘$’行尾,'^'非空白行首,'0'行首 ‘ ...
- Pytest系列(7) - skip、skipif跳过用例
如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 pytest.mark.sk ...
随机推荐
- CVE-2019-16278-Nostromo Web Server远程代码执行
本文主题主要是分析CVE-2019-16278漏洞原因.漏洞如何利用以及为什么会受到攻击.这个CVE跟Nostromo Web服务器(又名nhttpd)有关,这个组件是在FreeBSD,OpenBSD ...
- nginx的rtmp搭建流媒体服务器实现直播流
最近自己搞了一个用nginx的rtmp来搭建流媒体服务器,从而实现直播的过程,参考了网上很多资料,有些资料对于初学者来说比较难以理解,在此将我搭建的过程记录下来,分享给大家. 1.下载nginx-rt ...
- nginx yaf需要注意的问题
nginx yaf需要注意的问题 显示视图的方法<pre> $this->getView()->assign(array('pack'=>$return['pack'], ...
- 1.2 lvm镜像卷
镜像能够分配物理分区的多个副本,从而提高数据的可用性.当某个磁盘发生故障并且其物理分区变为不可用时,您仍然可以访问可用磁盘上的镜像数据.LVM 在逻辑卷内执行镜像. 系统版本: # cat /etc ...
- beanshell 通过java写数据到文件
import java.io.*; String filePath = "/data/account.txt"; String conent = vars.get("ac ...
- was unable to refresh its cache! status = Cannot execute request on any known server
出现这种错误是因为: Eureka服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为. 在 yml中设置 eureka.client.register-with-eu ...
- Vuecli3
第一步安装 npm install -g @vue/cli 第二步关于项目配置 因为cli3去除了cli2中index.html 转而存到了publi文件中 如果需要配置跨域 页面入口 打包文件路径都 ...
- linux查看当前路径命令 pwd
pwd命令能够显示当前所处的路径. 这个命令比较简单,如果有时在操作过程中忘记了当前的路径,则可以通过此命令来查看路径,其执行方式为: # pwd /home/your_username 第一行为运行 ...
- jdbc 简单示例和优缺点
一个使用JDBC的例子: Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动 Connection connection = Dri ...
- QRCode.js:使用 JavaScript 生成微信二维码
https://www.runoob.com/w3cnote/javascript-qrcodejs-library.html 什么是 QRCode.js? QRCode.js 是一个用于生成二维码的 ...