suxxsfe

一言(ヒトコト)

CF1425E Excitation of Atoms

http://codeforces.com/problemset/problem/1425/E

\(sum_i\) 为前缀和,\(gain_i\)\(\max sum_n-sum_{j-1}-D_j,j\ge i\)\(gain2_i\)\(\max sum_n-sum_{j-1}-D_j,j\le 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,j\le i\) 的代价
如果要激发 \([i+1,n]\) 中的某个子段,用 \(gain\) 计算
答案为 \(sum_i-min+\max(gain_{i+1},0)\),枚举所有 \(i\) 取最大值

\(E_{i-1}\) 向后改,此时肯定改为 \(i+1\),否则少取中间跳过的一段也不会最优
如果激发点 \(j\ge 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;
}
posted @ 2020-10-30 20:36  suxxsfe  阅读(123)  评论(0编辑  收藏  举报