CodeForces 947B - Producing Snow
思路
注意:数字较大,用 long long
转化:反过来考虑每一堆对每一天融化量的贡献值,即对第i堆,计算从第i天开始能撑多少天。
算法:累加前缀和,利用二分的upper_bound找出第一个大于第i堆的天数,即当前堆完全融化的天数,利用线段树区间增减,然后乘上倍数再加上多出的部分
代码
#include <bits/stdc++.h>
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<<ans[i]<<" ";
}
}
int main(){
//freopen("datain.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
}