http://codeforces.com/problemset/problem/1425/E
设 (sum_i) 为前缀和,(gain_i) 为 (max sum_n-sum_{j-1}-D_j,jge i),(gain2_i) 为 (max sum_n-sum_{j-1}-D_j,jle i)
k=0
显然 (ans=max(gain_1,0))
k>1
构造,对于一个 (i),将 (E_i) 改为 (1),将 (E_{i-1}) 改为 (i+1)
这样可以激发所有原子,只要将 (i) 选为 (D_i) 最小的即可
k=1
分两种情况
将 (E_i) 向前改,此时肯定改为 (1),同样代价把前面都选上才会最优
这样如果要激发 ([1,i]),只需花费 (min=min D_j,jle i) 的代价
如果要激发 ([i+1,n]) 中的某个子段,用 (gain) 计算
答案为 (sum_i-min+max(gain_{i+1},0)),枚举所有 (i) 取最大值
将 (E_{i-1}) 向后改,此时肯定改为 (i+1),否则少取中间跳过的一段也不会最优
如果激发点 (jge i),答案为 (gain_i),和 (k=0) 的类似
如果激发点 (j<i),那么会激发 ([j,n]) 所有点除去 (i),再考虑 (i) 要不要单独激发一下,答案是 (gain2_{i-1}-min(D_i,A_i))
单独再激发一下 (i) 的情况已经包含了两个激发点同时在 (i) 的前后,不用单独考虑这种两个激发点的情况了
仍然枚举 (i) 取最大值
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#define reg register
inline int read(){
register int x=0;register int y=0;
register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')y=1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return y?-x:x;
}
#define N 100006
int n;
long long sum[N],a[N],gain[N],gain_[N];
long long d[N];
int main(){
n=read();int k=read();
for(reg int i=1;i<=n;i++) sum[i]=sum[i-1]+(a[i]=read());
for(reg int i=1;i<=n;i++) d[i]=read();
for(reg int i=1;i<=n;i++) gain[i]=sum[n]-sum[i-1]-d[i],gain_[i]=std::max(gain_[i-1],gain[i]);
for(reg int i=n-1;i;i--) gain[i]=std::max(gain[i],gain[i+1]);
if(!k) return printf("%lld",std::max(gain[1],0ll)),0;
if(k>1){
long long ans=sum[n]-d[1];
for(reg int i=2;i<n;i++) ans=std::max(ans,sum[n]-d[i]);
ans=std::max(ans,a[n]-d[n]);
printf("%lld",std::max(ans,0ll));
return 0;
}
long long ans=0;
long long min=std::min(d[1],d[2]);
for(reg int i=2;i<n;i++){
ans=std::max(ans,sum[i]-min+std::max(0ll,gain[i+1]));//向前改
min=std::min(min,d[i+1]);
}
for(reg int i=2;i<n;i++){
ans=std::max(ans,std::max(gain[i],gain_[i-1]-std::min(a[i],d[i])));//向后改
// ans=std::max(ans,gain[])
}
for(reg int i=2;i<=n;i++) ans=std::max(ans,sum[n]-sum[i-1]-d[i]);
printf("%lld",ans);
return 0;
}