您的位置:首页 > 其它

bzoj 2124: 等差子序列

2017-10-07 21:15 302 查看

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

Source

这个题好妙啊;

题目是要找到 i<j<k,使得a[j]-a[i]=a[k]-a[j];

我们考虑按顺序插入a[],对于我们当前位置j,如果有一个a[i]已经出现了,但是a[k]还没有出现,因为是排列,所以这个a[k]必然在后面,所以答案为"Y;

我们用一个辅助数组b[],按顺序如果x出现了,就标记为1,那么如果一个数x满足条件,那么必然有b[x-y]!=b[x+y],那么只需要判断以x为中心的最长的字符串是否为回文串即可;

以为如果不是回文串那么必然能找到一个b[x-y]!=b[x+y],所以答案为"Y",判断回文串可以用正反两边hsh,然后hsh值要动态修改,所以用树状数组和线段树都可以;

如果用线段树的话就是提取hsh值的时候在递归左区间的时候*pre[r-mid],我自己写的是树状数组,涉及单点修改和前缀查询,只不过在修改和询问的时候都要*pre[];

//MADE BY QT666
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=100050;
int pre
,n;
int lowbit(int x){return x&-x;}
struct data{
int hsh
;
void update(int x){
for(int i=x;i<=n;i+=lowbit(i)) hsh[i]+=pre[i-x];
}
int query(int x){
int ret=0;
for(int i=x;i;i-=lowbit(i)) ret+=hsh[i]*pre[x-i];
return ret;
}
int ask(int l,int r){
return query(r)-query(l-1)*pre[r-l+1];
}
}bit,bit2;
int main(){
int T;scanf("%d",&T);
pre[0]=1;for(int i=1;i<=10050;i++) pre[i]=pre[i-1]*3;
while(T--){
scanf("%d",&n);int flg=0;
memset(bit.hsh,0,sizeof(bit.hsh));
memset(bit2.hsh,0,sizeof(bit2.hsh));
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
int len=min(x-1,n-x);if(flg) continue;
if(len&&bit.ask(x-1-len+1,x-1)!=bit2.ask(n-x-len+1,n-x)) {puts("Y"),flg=1;}
bit.update(x);bit2.update(n-x+1);
}
if(!flg) puts("N");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: