一.题目
题目描述
小可家门口的路历经沧桑,已经不复平坦,变得坑坑洼洼的。
于是小可拜托达达找了一个施工队来修补道路。施工队把这个道路分成了 n 段,然后测量了这 n 段各自的高度。
施工队的人对小可说:“我们现在要通过两种方式按段修复这条道路:1 、对有些路段填充一些材料,增加 x 高度。 2 、对有些路段削减掉 x 的高度。当然有的路段我们可能什么都不做。”
x 是一个固定值,小可并不知道具体是多少。但是小可想知道通过这种方式,有没有可能让这个道路重新变得平坦。
输入描述
第一行一个正整数 n (1≤ n≤ 105)
第二行有 n 个整数 ai (0≤ a_i≤ 109),代表每段路的高度。
输出描述
如果可能重新变得平坦,输出"YES"。否则输出"NO"。平坦即为所有路段高度都相同。
样例
输入
5 1 3 3 2 1
输出
YES
二.思路
由于x并没有给出具体值,因此需要我们去构造。但这个题不是让我们找出x,而是问有没有方法。
因此我们只需要去重,然后分类讨论判断就可以了。
很容易想出用set
三.代码详解
开set
set<long long> se;
在输入的过程中将数据插入进set
for(int i=1;i<=n;i++){
cin>>t;//t是之前开好的
se.insert(t);
}
开始分类讨论。定义len=se.size();
因为set自带去重特性,所以若len为1(无需修补)或len为2(选择一个加/减),一定可以修补。
if(len==1||len==2){
printf("YES");
}
若len为3,有两种情况。
1. 三个数等差。此时x=公差。
(例:去重后se里是1 3 5,x=3-1=5-3。)
2. 三个数不等差。此时无解
(例:去重后se里是1 3 4,无论基准选哪个,x都有两个值。)
if(len==3){
long long a[4],tot=1;
for(set<ll>::iterator it=se.begin();it!=se.end();it++){
a[tot++]=*it;
}
if(a[2]-a[1]==a[3]-a[2]){
printf("YES");
}
else{
printf("NO");
}
}
若len=4,一定无解。(x至少有两个值)
if(len==4){
printf("NO");
}
四.AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,t;
set<ll>se;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>t;
se.insert(t);
}
ll len=se.size();
if(len==1||len==2){
printf("YES");//若len为1(无需修补)或len为2(选择一个加/减),一定可以修补
}
else if(len==3){
ll a[4],tot=1;
for(set<ll>::iterator it=se.begin();it!=se.end();it++){
a[tot++]=*it;
}
if(a[2]-a[1]==a[3]-a[2]){
printf("YES");//此时x=公差,有解
}
else{
printf("NO");//否侧无解
}
}
else{
printf("NO");//若len=4,一定无解
}
return 0;
}