题目链接
比赛的时候这题被Hack了真的无比伤心,赛后看了很多篇代码,大多O(
n2
),下面介绍O(
n
<script type="math/tex" id="MathJax-Element-235">n</script>)的做法
相邻的两个点,要么在同一条直线上,要么在不同的直线上,共有三种情况,如图所示
设直线的斜率为p(由于题目中相邻两个点的横坐标差值为1,所以如果在同一条直线上的话相邻两点的纵坐标差值即为斜率),设两条平行直线在同一横坐标下纵坐标差值的绝对值为q
下面分析三种情况下,相邻两个点的纵坐标差值
情况1:p
情况2:p+q
情况3:p-q
大致思路如上所述,代码实现过程中有许多细节,比如差分处理之后出现过的不同数值只能是两种或三种才有可能满足题目条件;情况2和情况3分别都不能连续出现,详见代码
#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct node
{
int dis,cnt;
bool operator < (const node& x) const { return dis<x.dis; }
}a[N];
int tot,n,x[N],y[N],i,j;
bool chk()
{
int tmp=0;
map<int,int>M;
for(i=1;i<n;i++){
for(j=0;j<tot;j++)if(y[i]==a[j].dis) break;
if(!j) tmp--;
else if(j==tot-1) tmp++;
M[tmp]=1;
}
return M.size()==2;
}
int main()
{
scanf("%d",&n);
for(tot=i=0;i<n;i++){
scanf("%d",&x[i]);
if(i){
y[i]=x[i]-x[i-1];
for(j=0;j<tot;j++)if(a[j].dis==y[i]) break;
if(j>=tot) a[tot++].dis=y[i];
a[j].cnt++;
}
}
if(tot==3){
sort(a,a+3); //排序后a[1]即情况1
puts(a[0].dis+a[2].dis==2*a[1].dis&&chk()?"Yes":"No");
}
else if(tot==2) puts(a[0].cnt==1||a[1].cnt==1||chk()?"Yes":"No");
else puts("No");
}