https://www.luogu.com.cn/problem/P2757
题意简化就是找到a[i] a[j] a[k]成一个len=3的等差数列,且a[j]-a[i]=a[k]-a[j]
那么枚举a[j],为方便从左到右枚举,设数字x在j左边为1,在右边为0
那么可以用树状数组维护一个hash值,如果a[j]+d和a[j]-d在不同边也就是一个是0一个是1,那么就存在一组等差序列了
也就是这个hash值如果不相等,说明某一对a[j]+d和a[j]-d分别在j的左边和右边,那么就有解
这个hash值要维护一个正着的一个倒着的,因为一边是+d一边是-d,我们要让a[j]-1和a[j]+1一一对应起来,就是将第一个树状数组b1的a[j]-1与b2的n-a[j]对齐,然后短的那边补成场的也就是乘以hash的base的那么多次幂,长的那边截取短的长度,看这两个值一不一样
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxl=1e5+10;
const int bas=1423333;
int n,ans;
int a[maxl],pre[maxl],suf[maxl];
ull mi[maxl];
struct bit
{
ull b[maxl];
inline void init()
{
for(int i=1;i<=n;i++)
b[i]=0;
}
inline void add(int i,ull x)
{
while(i<=n)
b[i]+=x,i+=i&-i;
}
inline ull sum(int i)
{
ull ret=0;
while(i)
ret+=b[i],i-=i&-i;
return ret;
}
}b1,b2;
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
inline void mainwork()
{
ans=0;
b1.init();b2.init();
for(int i=2;i<=n-1;i++)
{
b1.add(a[i-1],mi[a[i-1]-1]);
b2.add(n-a[i-1]+1,mi[n-a[i-1]]);
int l1=a[i]-1,l2=n-a[i];
if(l1==0 || l2==0) continue;
if(l1<l2)
{
ull x1=b1.sum(a[i]-1);
ull x2=b2.sum(n-a[i])-b2.sum(n-a[i]-l1);
if(x1*mi[l2-l1]!=x2)
ans=1;
}
else
{
ull x1=b1.sum(a[i]-1)-b1.sum(a[i]-1-l2);
ull x2=b2.sum(n-a[i]);
if(x1!=x2*mi[l1-l2])
ans=1;
}
}
}
inline void print()
{
puts(ans?"Y":"N");
}
int main()
{
mi[0]=1;
for(int i=1;i<maxl;i++)
mi[i]=mi[i-1]*bas;
int t;
scanf("%d",&t);
while(t--)
{
prework();
mainwork();
print();
}
return 0;
}