一个FST好题! ??
我们先分情况讨论。
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的策略实在是太多了,需要全部考虑:
具体看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;
}
CF 1425 E. Excitation of Atoms 题解
原文:https://www.cnblogs.com/gary-2005/p/14013522.html