CodeForces 947B - Producing Snow

CodeForces 947B - Producing Snow

思路

注意:数字较大,用 long long
转化:反过来考虑每一堆对每一天融化量的贡献值,即对第i堆,计算从第i天开始能撑多少天。
算法:累加前缀和,利用二分的upper_bound找出第一个大于第i堆的天数,即当前堆完全融化的天数,利用线段树区间增减,然后乘上倍数再加上多出的部分

代码

#include 
using namespace std;

typedef long long LL;
const LL N=1e5+2;

#define ls rt<<1
#define rs rt<<1|1
#define lson ls,l,m
#define rson rs,m+1,r
#define root 1,1,n

LL SUM[4*N],add[4*N],ans[N+1];
void PushUp(LL rt,LL l,LL r){
    SUM[rt]=SUM[ls]+SUM[rs];
}

void PushDown(LL rt,LL l,LL r){
    if (add[rt]){
        LL m=(l+r)>>1;
        SUM[ls] += add[rt]*(m-l+1);
        SUM[rs] += add[rt]*(r-m);
        add[ls] += add[rt];
        add[rs] += add[rt];
        add[rt]=0;
    }
}
void LLerval_add(LL p,LL L,LL R,LL rt,LL l,LL r){
    if (L<=l && r<=R){
        add[rt]+=p;
        SUM[rt]+=(r-l+1)*p;
        return;
    }
    PushDown(rt,l,r);
    LL m=(l+r)>>1;
    if (L<=m) LLerval_add(p,L,R,lson);
    if (R>m)  LLerval_add(p,L,R,rson);
    PushUp(rt,l,r);
}
void query_all(LL rt,LL l,LL r){
    if (l==r){
        ans[l]=SUM[rt];
        return;
    }
    PushDown(rt,l,r);
    LL m=(l+r)>>1;
    query_all(lson);
    query_all(rson);
}
void solve(){
    LL n;
    cin>>n;
    LL v[n+1],sumt[n+1],tmp[n+2],t[n+1];
    for (LL i=1;i<=n;i++) cin>>v[i];
    memset(sumt,0,sizeof(sumt));
    memset(SUM,0,sizeof(SUM));
    memset(add,0,sizeof(add));
    for (LL i=1;i<=n;i++) {
        cin>>t[i];
        tmp[i]=0;
        sumt[i]=sumt[i-1]+t[i];
    }
    for (LL i=1;i<=n;i++){
        LL pos=upper_bound(sumt+1,sumt+n+1,v[i]+sumt[i-1])-sumt;
        if (pos>i) LLerval_add(1,i,pos-1,root);
        if (pos) tmp[pos]+=(v[i]+sumt[i-1]-sumt[pos-1]);
    }
    query_all(root);
    for (LL i=1;i<=n;i++){
        ans[i]*=t[i];
        ans[i]+=tmp[i];
        cout<" ";
    }
}
int main(){
    //freopen("datain.txt","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
}

你可能感兴趣的:(CodeForces 947B - Producing Snow)