Wine Factory
Win Factory
题意已经很简明了,这里不加以阐述,注意到
到这里,其实求解策略就很明显了,从第
要是这题没有修改就已经贪心做完了,在有修改的情况下,数学功底比较好的人可以把答案用式子表示出来然后硬推,这里提供一种不同的思考方向。
考虑这样一个问题:假设水足够多,那么答案就是巫师的法力总和,但是在大多时候答案却小于这个值,少的那一部分去哪里了呢?也就是说巫师的法力在什么情况下会浪费掉?
显然,对于水桶
如果对这个值做一遍前缀和是什么呢?令
理解完过程后,再来看如何计算浪费值,图中两段粉线相加即为浪费值,显然,它们相加就是最高点的高度,即
有了浪费值,答案就是法力总和减掉浪费值,即
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+7;
int n,m,id,x,y,sum;
int a[maxn],b[maxn],s[maxn],dat[maxn<<2],laz[maxn<<2];
void pushdown(int rt){
if(laz[rt]){
dat[rt<<1]+=laz[rt];
dat[rt<<1|1]+=laz[rt];
laz[rt<<1]+=laz[rt];
laz[rt<<1|1]+=laz[rt];
laz[rt]=0;
}
return ;
}
void build(int rt,int l,int r){
if(l==r){
dat[rt]=s[l];
return ;
}
int mid=l+r>>1;
build(rt<<1,l,mid),build(rt<<1|1,mid+1,r);
dat[rt]=max(dat[rt<<1],dat[rt<<1|1]);
return ;
}
void update(int rt,int l,int r,int x,int y,int val){
if(x<=l&&y>=r){
dat[rt]+=val,laz[rt]+=val;
return ;
}
int mid=l+r>>1;
pushdown(rt);
if(x<=mid) update(rt<<1,l,mid,x,y,val);
if(y>mid) update(rt<<1|1,mid+1,r,x,y,val);
dat[rt]=max(dat[rt<<1],dat[rt<<1|1]);
return ;
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) scanf("%lld",&b[i]),sum+=b[i];
for(int i=1;i<=n;i++) s[i]=s[i-1]+b[i]-a[i];
for(int i=1;i<n;i++) scanf("%*lld");
build(1,1,n);
while(m--){
scanf("%lld%lld%lld%*lld",&id,&x,&y),sum+=y-b[id];
update(1,1,n,id,n,y-x-(b[id]-a[id]));
a[id]=x,b[id]=y;
printf("%lld\n",sum-max(dat[1],0ll));
}
return 0;
}