题意:
爱丽丝每天会堆一堆雪体积为 Vi,每天的温度是Ti,每天还存在的雪堆就会融化 Ti 的体积,问每天融化雪体积的总量是多少。
思路:
可以将温度维护一个前缀和,对于每个雪堆每次就可以二分查找到这个雪堆完全融化是在第几天,假如第 i 天的雪堆二分查找到是在第 j 天融化完,那么就可以对 [ i , j ) 这个区间都加1 (使用线段树维护)意味着融化了一个完整的 Ti ,第 j 天融化的雪量单独记下来,最后查找融化了多少。
代码:
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int max_n=100100;
typedef long long Lint;
Lint a[max_n];
struct Node{
Lint sum;
Lint add;
int ls;
int rs;
}tree[max_n<<2];
void Build(int num,int l,int r){
tree[num].ls=l;
tree[num].rs=r;
tree[num].add=0;
if(l==r){
tree[num].sum=a[l];
return;
}
int mid=(l+r)/2;
Build(num<<1,l,mid);
Build(num<<1|1,mid+1,r);
tree[num].sum=tree[num<<1].sum+tree[num<<1|1].sum;
return;
}
void pushdown(int num,int ls,int rs){
if(tree[num].add!=0){
tree[ls].sum+=tree[num].add*(tree[ls].rs-tree[ls].ls+1);
tree[rs].sum+=tree[num].add*(tree[rs].rs-tree[rs].ls+1);
tree[ls].add+=tree[num].add;
tree[rs].add+=tree[num].add;
tree[num].add=0;
}
}
void Update(int num,int l,int r,int fl,int fr,int val){
if(fl>r || fr<l) return;
if(fl<=l && r<=fr){
tree[num].sum+=(tree[num].rs-tree[num].ls+1)*val;
tree[num].add+=val;
return;
}
//if(l==r) return;
pushdown(num,num<<1,num<<1|1);
int mid=(l+r)>>1;
Update(num<<1,l,mid,fl,fr,val);
Update(num<<1|1,mid+1,r,fl,fr,val);
tree[num].sum=tree[num<<1].sum+tree[num<<1|1].sum;
return ;
}
Lint Query(int num,int l,int r,int fl,int fr){
if(fl>r || fr<l) return 0;
if(fl<=l && r<=fr) return tree[num].sum;
pushdown(num,num<<1,num<<1|1);
int mid=(l+r)/2;
Lint res1=Query(num<<1,l,mid,fl,fr);
Lint res2=Query(num<<1|1,mid+1,r,fl,fr);
return res1+res2;
}
以上为线段树区间更新模板
Lint vv[max_n];
Lint tt[max_n];
Lint res[max_n];
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%lld",&vv[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&tt[i]);
tt[i]+=tt[i-1];
}
for(int i=1;i<=n;i++){
int index=lower_bound(tt+i,tt+n+1,tt[i-1]+vv[i])-(tt);
int l,r;
// cout<<"index=="<<index<<endl;
res[index]+=vv[i]-(tt[index-1]-tt[i-1]);
l=i; r=index-1;
if(l<=r){
Update(1,1,n,l,r,1);
}
}
for(int i=1;i<=n;i++){
res[i]+=Query(1,1,n,i,i)*(tt[i]-tt[i-1]);
}
for(int i=1;i<=n;i++){
printf("%lld%c",res[i],i==n?'\n':' ');
}
}
int main(){
solve();
return 0;
}