CF 1425 E. Excitation of Atoms 题解

CF 1425 E. Excitation of Atoms 题解

一个FST好题! 👍

我们先分情况讨论。

  1. k=0,这没啥好说的,枚举每一个位置即可。
  2. k=1,比较复杂。。
  3. k=2,还是比较复杂。。
  4. k=3...
  5. ...

k很多的时候就非常复杂了,我们可以先摸索摸索策略。

由于n没有出边,所以你激活n的时候不会影响到其它的原子。所以我们尽量不直接激活n。

假设前n-1个原子中di最小的是j。我们能否只激活j,然后就激活了所有呢?

我们可以这样构造:

1->2->...->j->j+1->...->n

将n-1连到1,形成一个环然后从j前面的位置断开。这样只需要2步就可以完成了。至于k>2的情况,可以前k-2步都是乱改,最后两部好好改。(注意,可能存在只需要激活n的情况)

我们一下就解决了所有k>=2的情况,但是这题的难点主要在于k=1!

k=1的策略实在是太多了,需要全部考虑:

  • 前i个形成环,后n-i个形成链
  • 跳过某一个i:将i-1改到i+1,激活1
  • 将链切成两半,将开头相连,激活那两个末端
  • 将1随便接到一个位置
  • ...

具体看code:

const int MAXN=1e5+20;
int n,k; 
int a[MAXN],d[MAXN];
LL suf[MAXN];
int main(){
	scanf("%d%d",&n,&k);
	rb(i,1,n) scanf("%d",&a[i]);
	rb(i,1,n) scanf("%d",&d[i]);
	LL rest=0;
	if(k==0){
		LL sum=0;
		rl(i,n,1){
			sum+=a[i];
			check_max(rest,sum-d[i]);
		}
	}
	else{
		if(k==1){
			LL sum=0;
			rl(i,n,2){
				sum+=a[i];
				check_max(rest,sum-d[i]);
			}
			rl(i,n,1)
				suf[i]=suf[i+1]+a[i];
			rl(i,n,1)
				suf[i]=max(suf[i+1],suf[i]-d[i]);
			check_max(rest,sum+a[1]-a[2]-d[1]);
			check_max(rest,sum+a[1]-a[n-1]-d[1]);
			sum-=a[n];
			sum+=a[1];
			int mini=INF;
			LL ssm=0;
			LL mi=INF;
			rb(i,1,n-1){
				check_min(mi,(LL)d[i]);
				ssm+=a[i];
				check_max(rest,ssm-mi+suf[i+1]);
			}
			rb(i,1,n-1)
				check_min(mini,d[i]);
			check_max(rest,sum-mini);
			mini=INF;
			rb(i,2,n){
				check_min(mini,a[i]);
			}
			check_max(rest,sum+a[n]-d[1]-mini);
			sort(d+1,d+n);
			check_max(rest,sum+a[n]-d[1]-d[2]);
		}
		else{
			LL sum=0;
			rl(i,n,1){
				sum+=a[i];
				check_max(rest,sum-d[i]);
			}
//			4 1
//10 10 9 100
//1 10 10 1000000
			int mini=INF;
			rb(i,1,n-1){
				check_min(mini,d[i]);
			}
			check_max(rest,sum-mini);
		}
	}
	cout<<rest<<endl;
	return 0;
}
posted @ 2020-11-20 23:27  WWW~~~  阅读(86)  评论(0编辑  收藏  举报