题目链接:Producing Snow
题意
Bob B o b 从第 1 1 天到第 天每天堆体积为 Vi V i 体积的雪人,第 i i 天的时候每一个已经堆好的雪人会融化 的体积,问在第 i i 天当天所有已经堆好的且没有完全融化的雪人会融化的总的体积。
输入
第一行包含一个整数 ,第 2 2 行包含 个整数 V1,V2,⋯,Vn (0≤Vi≤109) V 1 , V 2 , ⋯ , V n ( 0 ≤ V i ≤ 10 9 ) ,第 3 3 行包含 个整数 T1,T2,⋯,Tn (0≤Ti≤109) T 1 , T 2 , ⋯ , T n ( 0 ≤ T i ≤ 10 9 ) 。
输出
输出 n n 个整数,第 个整数表示第 i i 天融化的雪人体积。
样例
输入 |
---|
3 10 10 5 5 7 2 |
输出 |
5 12 4 |
提示 |
第一天堆了一个体积为 的雪人,融化了 5 5 的体积,剩下一个体积为 的雪人,第二天堆了一个体积为 10 10 的雪人,每个雪人都融化 7 7 的体积,第一天的 体积的雪人全都融化了,第二天的雪人融化了 7 7 体积,总共融化了 体积,第二天只剩下一个体积为 3 3 的雪人,第三天堆了一个体积为 的雪人,第二天雪人剩下的体积和第三天雪人的体积都大于等于第三天融化的体积,第三天总共融化了 4 4 体积的雪人。 |
输入 |
---|
5 30 25 20 15 10 9 10 12 4 13 |
输出 |
9 20 35 11 25 |
题解
假设第 天堆起来的雪人体积为无穷大,那么到第 i i 天的时候这个雪人融化的体积就为 ,第 i i 天刚堆起来的雪人没有受到前 天融化的影响,但是可以假设这个雪人是从第 1 1 天堆起来的,第 天的时候融化了 ∑i−1j−1Ti ∑ j − 1 i − 1 T i 的体积,导致它第 i i 天的体积为 ,因此可以认为这个雪人在第 1 1 天堆起来的时候的体积为 ,我们将到第 i i 天的所有雪人的体积都转化为 后放入 map m a p 中,到第 i i 天完全融化的雪人就是 的雪人,将这些雪人在第 i i 天融化的体积()计算出来,然后从 map m a p 中删去它们,再计算第 i i 天能融化体积 的雪人的个数 cnt c n t (可以 O(1) O ( 1 ) 维护),于是第 i i 天融化的雪人体积就为 ,其中 ∑i−1k=1Tk<V′j≤∑ik=1Tk ∑ k = 1 i − 1 T k < V j ′ ≤ ∑ k = 1 i T k 。
过题代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const int maxn = 100000 + 100;
int n, cnt;
LL mp_cnt;
map<LL, int> mp;
map<LL, int>::iterator it, itt;
LL v[maxn], t[maxn];
map<LL, int>::iterator del[maxn];
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
while(scanf("%d", &n) != EOF) {
mp_cnt = 0;
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &v[i]);
}
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &t[i]);
t[i] += t[i - 1];
}
mp.clear();
LL ans;
for(int i = 1; i <= n; ++i) {
ans = 0;
cnt = 0;
v[i] += t[i - 1];
++mp[v[i]];
++mp_cnt;
it = mp.upper_bound(t[i]);
for(itt = mp.begin(); itt != it; ++itt) {
ans += ((itt->first) - t[i - 1]) * (itt->second);
del[cnt++] = itt;
mp_cnt -= itt->second;
}
for(int j = 0; j < cnt; ++j) {
mp.erase(del[j]);
}
ans += mp_cnt * (t[i] - t[i - 1]);
if(i != 1) {
printf(" ");
}
printf("%I64d", ans);
}
printf("\n");
}
return 0;
}