Codeforces 371(#218 Div2 only) D. Vessels
問題
n枚の皿があって、i番目の皿の容量はa[i]リットル。
i番目の皿に水を注いで、容量を超えた分はi+1番目の皿に溢れる。(i+1番目の皿も一杯ならi+2番目に……となる)
n番目の皿から溢れた水は捨てられる。
次のクエリがm個来るので答えよ。
- i番目の皿にxリットルの水を注ぐ
- i番目の皿の水の容量を答える
制約条件
n≦2*10^5
m≦2*10^5
a[i]≦10^9
方針
i番目の皿に注いだときに入る皿を、union-find的な構造を使って実装すればはやい。
ならし計算量でlog nとかそれくらい。
それ以外の操作は愚直でいい。
皿が一杯になる回数は全部で高々n回だし、クエリはm個しかないから。
ソースコード
const int N = 200001; int p[N]; int to(int x){ if(p[x] == x) return x; return p[x] = to(p[x]); } int n, a[N]; int m, b[N]; int main(){ cin >> n; rep(i, n) cin >> a[i], p[i] = i; p[n] = n; cin >> m; while(m--){ int type, t, x; cin >> type >> t; t--; if(type == 1){ cin >> x; t = to(t); while(x > 0 && t < n){ int pour = min(a[t] - b[t], x); b[t] += pour; x -= pour; if(b[t] == a[t]){ p[t] = to(t + 1); t = to(t + 1); } } } else{ cout << b[t] << endl; } } return 0; }