Codeforces 948C - Producing Snow (树状数组)

题目链接

http://codeforces.com/contest/948/problem/C

刚讲完树状数组的第一场cf就遇到了,然而没做出来,次日怒补之,同时写篇题解自省。


题目大意

每天新造一堆体积为v[i]的雪,同时所有的雪堆都融化t[i]的体积,体积<=0时雪堆消失,问每天融掉的雪的总体积。


解题分析

令num[i]为第i天的剩余雪堆数,rem[i]为将在该天消失的雪的总体积,则第i天融掉的雪的总体积为num[i]*t[i]+rem[i]。
用树状数组sum[i]维护t[i]的前缀和,则对每个v[i],可以用二分O(lognlogn)地算出在将第j天消失,继而从i到j-1的num++(修改两点即可),同时rem[j]+=剩余体积。
总时间复杂度O(nlognlogn)。


AC代码

#include<bits/stdc++.h>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
const int MAXN = 100010;

template<typename T> inline void R(T &x) {
    char ch = getchar(); x = 0;
    for (; ch < '0'; ch = getchar());
    for (; ch >= '0'; ch = getchar()) x = x * 10 + ch - '0';
}

int n;
int v[MAXN];
int t[MAXN];
LL sum[MAXN];
LL num[MAXN];
LL rem[MAXN];

LL ask(int x)
{
    LL ans = 0 ;
    for(; x ; x-=lowbit(x) ) ans += sum[x];
    return ans ;
}

void add(int x,int y)
{
    for(; x<=n ; x+=lowbit(x) ) sum[x] += y;
}

int main()
{
    cin>> n;
    for(int i = 1; i <= n; i ++) R(v[i]);
    for(int i = 1; i <= n; i ++) R(t[i]);
    for(int i = 1; i <= n; i ++) add(i , t[i]);
    for(int i = 1; i <= n; i ++){
        int l = i, r = n , res = n + 1;
        while(l <= r){
            int mid = (l + r)/2;
            LL tmp = ask(mid) - ask(i - 1);
            if( tmp > v[i] ) res = mid, r = mid - 1;
            else l = mid + 1;
        }
        rem[res] += v[i] - (ask(res - 1) - ask(i - 1));
        num[i] ++;
        num[res] --;
    }
    for(int i = 1; i <= n; i ++){
        num[i] += num[i-1] ;
        cout<< num[i] * t[i] + rem[i] <<' ';
    }
    cout<< endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Hrbust_cx/article/details/79521838