CF Round #218 (Div. 2) && CF 371D Vessels【并查集】

D. Vessels

time limit per test  2 seconds

memory limit per test      256 megabytes


There is a system ofn vessels arranged one above the otheras 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 thei-th vessel isai liters.

Initially, all the vessels are empty. In some vessels water ispoured. All the water that overflows from thei-th vessel goes to the(i + 1)-th one. The liquid thatoverflows from the n-th vessel spills on the floor.

Your task is to simulate pouring water into the vessels. To dothis, you will need to handle two types of queries:

1. Addxi liters of water to the pi-th vessel;

2. Print the number of liters of water in theki-th vessel.

When you reply to the second request you can assume that all thewater poured up to this point, has already overflown between the vessels.

Input

The first line contains integern — the number of vessels (1 ≤ n ≤ 2·105). The second line containsn integersa1, a2, ..., an — the vessels' capacities(1 ≤ ai ≤ 109). The vessels' capacitiesdo not necessarily increase from the top vessels to the bottom ones (see thesecond sample). The third line contains integerm — the number of queries (1 ≤ m ≤ 2·105). Each of the next m lines contains the description of onequery. The query of the first type is represented as "pi xi", the query of thesecond type is represented as "ki" (1 ≤ pi ≤ n,1 ≤ xi ≤ 109,1 ≤ ki ≤ n).

Output

For each query, print on a single line the number of liters of water in thecorresponding vessel.

Examples

Input

2
5 10
6
1 1 4
2 1
1 2 5
1 1 4
2 1
2 2

Output

4
5
8

Input

3
5 10 8
6
1 1 12
2 2
1 1 6
1 3 2
2 2
2 3

Output

7
10
5

 


【题意】有n个有固定容积的容器从下往上依次堆叠,从上往下为他们编号:1~n,现在有q个两种操作,一种是往第i个盘子中注水(如果满出,则多余的水流入第i+1个盘子,以此类推,如果最后一个盘子满出,多余的水流向地面,不再计算),还有一种操作是输出第i个盘子现在的水量。

【分析】由于n,q较大,如果利用暴力去更新水量的话,复杂度高达O(n*q)显然会超时,那我们就要想办法去掉在一系列都已经盛满的容器间转移的时间。所以我们就需要把连续的装满水的容器合并成一个,这样就能大大优化时间。

具体实现方法就是利用并查集,如果注水时当前容器已满,那么就把与下一个容器合并,即pre[i]=i+1,(其实应该是pre[find(i)]=find(i+1),即并查集里的 join ()函数),而且我们每次开始注水时,应该直接对find(i)注水。

这样的做法就可以在O(nlogn)的时间复杂度下出结果啦。


#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define f(i,a,b) for(int i=(a);i<=(b);++i)
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn=200005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;

int pre[maxn];
int a[maxn];
int ans[maxn];

int find(int x)
{
    int t,r=x;
    while(pre[x]!=x)
    {
        x=pre[x];
    }
    while(r!=x)
    {
        t=pre[r];
        pre[r]=x;
        r=t;
    }
    return x;
}

void join(int a,int b)
{
    int A=find(a);
    int B=find(b);
    if(A>B)
    {
        pre[B]=A;
    }
    else pre[A]=B;
}

int main()
{
    int n,m;
    int order;
    int pos,w;
    scanf("%d",&n);
    mst(ans,0);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        pre[i]=i;
    }
    pre[n+1]=n+1;                          //特别注意
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d",&order);
        if(order==1)
        {
            scanf("%d%d",&pos,&w);
            while(w>0)
            {
                pos=find(pos);
                if(pos==n+1)               //特别注意
                    break;
                if(a[pos]-ans[pos]>w)
                {
                    ans[pos]+=w;
                    w=0;
                }
                else
                {
                    w-=(a[pos]-ans[pos]);
                    ans[pos]=a[pos];
                    join(pos,pos+1);
                }
            }
        }
        else if(order==2)
        {
            scanf("%d",&pos);
            printf("%d\n",ans[pos]);
        }
    }
    return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值