トレーニング4 - I题
以下の図に示すように、互いに上下に配置されたn個の容器のシステムがあります。容器は、最高から最低にするために、i番目の容器の容積はリットル愛される、1からnまでの番号が付けられていると仮定する。
最初は、すべての船舶は空です。いくつかの容器に水が注がれています。i番目の容器から溢れすべての水は、(i + 1)番目のいずれかに進みます。n番目の容器から溢れた液体が床にこぼれ。
あなたの仕事は、容器に水を注ぐシミュレートすることです。これを行うには、クエリの2つのタイプを処理する必要があります。
パイ番目の容器に水のXIリットルを追加します。
KI番目の容器内の水のリットル数を出力します。
あなたは2番目のリクエストに返信するときは、すべての水は、この時点までに注ぐと仮定することができ、すでに容器の間オーバーフローしました。
入力
最初の行は、整数N含ま - 血管の数(1≤N≤2・105)。船舶の容量(1≤109愛≤) - 2行目はnは整数A1、A2、...、含まれています。船舶の容量は必ずしも一番下のもの(第二のサンプルを参照)にトップの血管から増加しません。クエリの数(1≤M≤2・105) - 第三行はMの整数含ま。次のm行の各々は、1つのクエリの記述を含みます。第一のタイプのクエリが「1つのパイXI」として表され、第二のタイプのクエリは「2 KI」として表される(1≤PI≤nは、1≤XI≤109、1≤KI≤N)。
出力
各クエリに対して、単一の行に対応する容器内の水のリットル数を印刷します。
例
入力
2
5 10
6
1 4
2 1
1 2 5
1 1 4
2 1
2 2
出力
4
5
8
入力
3
5 10 8
6
1 1 12
2 2
1 1 6
1 3 2
2 2
2 3
出力
7
10
5
#pragma warning (disable:4996)
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define inf 0X3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 5;
int f[maxn];//连续的满的容器
int get(int x)
{
if (f[x] == x)
return x;
return f[x] = get(f[x]);
}
void merge(int x, int y)
{
f[get(x)] = get(y);
}
int a[maxn];
int l[maxn];
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
f[i] = i;
scanf("%d", &a[i]);
}
int m;
scanf("%d", &m);
while (m--)
{
int oper;
scanf("%d", &oper);
if (oper == 1)
{
int p, x;
scanf("%d%d", &p, &x);
int tmp = p;
while (l[tmp] + x > a[tmp])
{
if (tmp > n || tmp <= 0)
break;
x -= (a[tmp] - l[tmp]);
l[tmp] = a[tmp];
merge(tmp, tmp + 1);
tmp = get(tmp + 1);
}
if (tmp <= n && tmp > 0)
l[tmp] += x;
}
if (oper == 2)
{
int k;
scanf("%d", &k);
printf("%d\n", l[k]);
}
}
return 0;
}
アイデア:
シンプル注ぐ水問題、時間のセーブ最適化するために、ばらばらのセットのレコードの連続水で満たされた容器で、次のフルコンテナダウンフルコンテナにわたって連続次回を注ぎます。