题解:P17728 [SCP-J 2026] 染色 / color
一道诈骗题,典型的贪心。
解题思路
首先看题目,题目要求出数列
依题意得,
消得只剩两项!我们有希望了。这就是著名的裂项相消 / 望远镜求和,也可以理解为对差分数组求前缀和可以得到原数组的元素。
如法炮制,我们把
接下来是第二个关键观察:因为
分类讨论:
- 若
A_1 与A_n 同色,不妨假设它们都在X 集合。原式变为A_{n}-A_{1}+A_{Y_{n-k}}-A_{Y_1} 。 - 若
A_1 与A_n 不同色,不妨假设1 在X 集合,n 在Y 集合。原式变为A_{n}-A_{1}+A_{X_k}-A_{Y_1} 。
不管怎样,原式都变为了
时间复杂度分析
处理读入和前缀最小值数组
AC code
考场上饭堂了,循环起点写错,喜提
:::success[代码]
#include<bits/stdc++.h>
#define ios cin.tie(0)->sync_with_stdio(0)
#define int i64
#define inf 0x7f7f7f7f7f7f7f7f
using namespace std;
typedef long long i64;
int a[202020],b[202020];
signed main()
{
int n,ans=-inf;
scanf("%lld",&n);
for(int i=0;i<n;i++){
scanf("%lld",a+i);
if(i) b[i]=min<int>(b[i-1],a[i]);
else b[i]=inf;
}
if(n==2){//小数据可以直接特判,避免出错
printf("%lld",max(a[1]-a[0],0ll));
return 0;
}
if(n==3){
printf("%lld",max<int>({a[2]-a[1],a[1]-a[0],a[2]-a[0]}));
return 0;
}
b[n]=b[n-1];
for(int i=0;i<n-1;i++){
ans=max<int>(ans,a[i]-b[i+1]);
}
ans=max<int>(ans,0ll);
printf("%lld",ans+a[n-1]-a[0]);
return 0;
}
:::