2124: 等差子序列
Description
给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
Input
输入的第一行包含一个整数T,表示组数。下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
Output
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
Sample Input
2
3
1 3 2
3
3 2 1
Sample Output
N
Y
HINT
对于100%的数据,N<=10000,T<=7
【解题报告】
来自:http://blog.csdn.net/lych_cys/article/details/51386628
题目就是求是否存在i < j < k,使得Ak-Aj=Aj-Ai。
我们不妨枚举中间那个数为x,然后按照输入的顺序对x进行操作。如果x满足条件,也就是存在两个数y和z,x-y=z-x,并且y已经出现过了而z还没有出现,那么我们就可以直接输出’Y’了。
因此,我们构造一个辅助数组b,其中x如果出现过,那么b[x]=1;否则b[x]=0。因此如果x满足条件,那么必然存在一个数y使得b[x-y]!=b[x+y];然后我们发现如果把b看成一个字符串,那么实际上就是判断以x为中心的极长字符串是否是回文串,如果不是那么显然存在y使得b[x-y]!=b[x+y],那么就可以输出’Y’。快速的字符串比较不妨使用hash,然后因为需要修改那么就用两个树状数组分别维护它所在区间正着和倒着的hash值即可。
代码如下:
/**************************************************************
Problem: 2124
User: onepointo
Language: C++
Result: Accepted
Time:812 ms
Memory:976 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10010
#define mod 1000000007
#define ll long long
#define lowbit(x) (x&(-x))
int t,n,a[N],pw[N];
struct bit_node
{
int c[N];
void clr(){memset(c,0,sizeof(c));}
void add(int x)
{
for(int i=x;i<=n;i+=lowbit(i)) c[i]=(c[i]+pw[i-x])%mod;
}
int getsum(int x){
int t=0;
for(int i=x;i;i^=lowbit(i)) t=((ll)c[i]*pw[x-i]+t)%mod;
return t;
}
int qry(int x,int y)
{
int p=getsum(x-1),q=getsum(y);
return (q-(ll)p*pw[y-x+1]%mod+mod)%mod;
}
}bit1,bit2;
int main()
{
pw[0]=1;
for(int i=1;i<=N;++i) pw[i]=(ll)pw[i-1]*12347%mod;
for(scanf("%d",&t);t;--t)
{
int x;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
bit1.clr();bit2.clr();
int i;
for(i=1;i<=n;++i)
{
x=min(a[i]-1,n-a[i]);
if(x&&bit1.qry(a[i]-x,a[i]-1)!=bit2.qry(n-a[i]-x+1,n-a[i])) break;
bit1.add(a[i]);bit2.add(n-a[i]+1);
}
puts((i>n)?"N":"Y");
}
return 0;
}