http://acm.hdu.edu.cn/showproblem.php?pid=3833
做这题还真是纠结啊,有很多小地方要注意。前面没有看清题义,题中给的数字是一个1-N的排列。
这题是这么做的,首先将每个数字的顺序通过数组记录起来,然后再根据 2*p[i2] = p[i1] + p[i3]进行暴力搜索。
搜索过程中要特别注意范围的选定,由于 p[i2] 是中间的一个数,所以其范围为 2 <= p[i2] <= N-1 ,而 p[i1] < p[i2] && p[i2] > p[i3];同时应该记得有范围 1 <= p[i1] <= N, 1 <= p[i3] <= N,前面就是没有把这个条件加进去,导致错了很多次。
推导如下: 右式可化为 1 <= 2*p[i2] - p[i1] <= N, 即 2*p[i2] - N <= p[i1] <= 2*p[i2] - 1,因为有p[i1] < p[i2],所以最后的式子为 MAX( 1, 2*p[i2] - N ) <= p[i2] <= p[i2]。
代码如下:
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
// p[ia] - p[ib] = p[ib] - p[ic] ==> 2 * p[ib] = p[ia] + p[ic];
// p[ib] 是中间项,取值为 [4, 2 * ( N - 1 ) ],再暴力
int a[10055];
int main()
{
int T;
scanf( "%d", &T );
while( T-- )
{
int N, flag = 0;
scanf( "%d", &N );
for( int i = 1; i <= N; ++i )
{
int c;
scanf( "%d", &c );
a[c] = i;
}
int lim = 2 * ( N - 1 );
for( int i = 4; i <= lim && !flag; i += 2 )
{
int beg = i > N ? ( i - N ) : 1, lim2 = i >> 1;
for( int j = beg; j < lim2 && !flag; ++j )
{
int k = i - j;
if( ( a[j] - a[lim2] ) * ( a[lim2] - a[k] ) > 0 )
{
flag = 1;
break;
}
}
}
puts( flag ? "Y" : "N" );
memset( a, 0, sizeof( a ) );
}
return 0;
}