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 ...
 
随机推荐
- 使用tuna源安装docker-ce
			
原文链接:https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/ sudo add-apt-repository \ "deb [arch= ...
 - 常用的js片段
			
1.检查是否为微信浏览器 function isWxBrowser() { var ua = navigator.userAgent.toLowerCase(); if (ua.match(/Micr ...
 - 使用事件和 CQRS 重写 CRUD 系统
			
使用事件和 CQRS 重写 CRUD 系统 https://msdn.microsoft.com/zh-cn/magazine/mt790196.aspx https://github.com/mem ...
 - asp.net core使用水晶报表问题
			
背景 最近项目上遇到一个需求,要后台通过定时任务把水晶报表生成pdf文件,然后邮件发送给相关人. 技术实现思路 选用ASP.NET Core框架(基于2.2版本),通过IHostedS ...
 - 防范sql注入值得注意地方
			
sql注入是大家基本都清楚,一般来说用参数化就能解决注入的问题,也是最好的解决方式. 有次技术群里问到一个问题,如下图 很显然tableName是外部传递过来的,暂时不考虑具体的业务环境,但如果以se ...
 - Data-Structure-Notes
			
Data Structure Notes Chapter-1 Sorting Algorithm Selection Sorting: /* * Selection Sort */ template& ...
 - Java的访问修饰符的作用范围
			
访问修饰符: private default protected public 作用范围: 访问修饰符\作用范围 所在类 同一包内其他类 其他包内子类 其他包内非子类 private 可以访问 不可以 ...
 - scala学习遇到的坑
			
1:软件是idea,在同一个包中,类名一样,会导致在调用类的时候,程序无法找到正确的类,最后出错. 2:return坑,在方法中,返回值的类型已经指定了,所以可以放心使用return,但是在函数中,没 ...
 - Ambari深入学习(III)-开源使用及其改进思考
			
Ambari采用的不是一个新的思想和架构,也不是完成了软件的新的革命,而是充分利用了一些已有的优秀开源软件,巧妙地把它们结合起来,使其在分布式环境中做到了集群式服务管理能力.监控能力.展示能力.这些优 ...
 - C语言--简易词法分析器
			
#include <stdio.h>#include <stdlib.h>#include <string.h>int p,m,syn,n,sum; / ...