Codeforces 923B Producing Snow(瞎搞)

题目链接:Producing Snow

题意

Bob B o b 从第 1 1 天到第 n 天每天堆体积为 Vi V i 体积的雪人,第 i i 天的时候每一个已经堆好的雪人会融化 Ti 的体积,问在第 i i 天当天所有已经堆好的且没有完全融化的雪人会融化的总的体积。

输入

第一行包含一个整数 n (1n105),第 2 2 行包含 n 个整数 V1,V2,,Vn (0Vi109) V 1 , V 2 , ⋯ , V n   ( 0 ≤ V i ≤ 10 9 ) ,第 3 3 行包含 n 个整数 T1,T2,,Tn (0Ti109) T 1 , T 2 , ⋯ , T n   ( 0 ≤ T i ≤ 10 9 )

输出

输出 n n 个整数,第 i 个整数表示第 i i 天融化的雪人体积。

样例

输入
3
10 10 5
5 7 2
输出
5 12 4
提示
第一天堆了一个体积为 10 的雪人,融化了 5 5 的体积,剩下一个体积为 5 的雪人,第二天堆了一个体积为 10 10 的雪人,每个雪人都融化 7 7 的体积,第一天的 5 体积的雪人全都融化了,第二天的雪人融化了 7 7 体积,总共融化了 12 体积,第二天只剩下一个体积为 3 3 的雪人,第三天堆了一个体积为 5 的雪人,第二天雪人剩下的体积和第三天雪人的体积都大于等于第三天融化的体积,第三天总共融化了 4 4 体积的雪人。
输入
5
30 25 20 15 10
9 10 12 4 13
输出
9 20 35 11 25

题解

假设第 1 天堆起来的雪人体积为无穷大,那么到第 i i 天的时候这个雪人融化的体积就为 j=1iTj,第 i i 天刚堆起来的雪人没有受到前 i1 天融化的影响,但是可以假设这个雪人是从第 1 1 天堆起来的,第 i 天的时候融化了 i1j1Ti ∑ j − 1 i − 1 T i 的体积,导致它第 i i 天的体积为 Vi,因此可以认为这个雪人在第 1 1 天堆起来的时候的体积为 Vi+j=1i1Tj,我们将到第 i i 天的所有雪人的体积都转化为 Vi=Vi+j=1i1Tj 后放入 map m a p 中,到第 i i 天完全融化的雪人就是 Vkj=1iTj 的雪人,将这些雪人在第 i i 天融化的体积(Vkj=1i1Tj)计算出来,然后从 map m a p 中删去它们,再计算第 i i 天能融化体积 Ti 的雪人的个数 cnt c n t (可以 O(1) O ( 1 ) 维护),于是第 i i 天融化的雪人体积就为 (Vjk=1i1Tk)+Ti×cnt,其中 i1k=1Tk<Vjik=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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值