題意:
給定一個長度為 \(n\) 的排列 \(a\),判斷其中是否有長度 \(\ge 3\) 的等差數列。
\(1 \le n \le 5 \times 10^5\)。
思路:
首先若存在長度 \(>3\) 的等差數列,則其中的一部分肯定由長度為 \(3\) 的等差數列組成;即我們現在只需要判斷是否存在長度為 \(3\) 的等差數列即可。
考慮列舉中間的數 \(a_i\),則問題轉化為 \(a_i-k\) 與 \(a_i + k\) 是否同時出現在 \(i\) 的兩側。
注意到 \(a\) 是一個排列,則是沒有重複數字的。
那麼我們可以記作若 \(i\) 左邊的 \(a_j\) 出現過,則將標記陣列中第 \(a_j\) 個位置為 \(0\)。
若不可以構成等差數列的話,當 \(a_i-k\) 被標記了,則 \(a_i+k\) 也必須被標記(不然就會出現在 \(i\) 右側,形成等差數列),那麼標記陣列就是以 \(i\) 為迴文中心迴文的。
現在我們需要支援單點賦值為 \(1\),判斷一個區間是否是迴文的;可以直接線段樹維護翻轉後和未翻轉時的雜湊值,判斷是否相等即為迴文。
考慮提前預處理出 \(base\) 的次冪,則單組資料時間複雜度為 \(O(N \log N)\)。
完整程式碼:
P2757 [國家集訓隊] 等差子序列
#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
#define For(i,l,r) for(int i=l;i<=r;i++)
#define _For(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=5e5+10;
const ull base=127;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
mt19937_64 R(time(0));
int T,n,x,l,r;
bool ans;
ull h[2],f[N];
class St{
public:
ull x,y;
int len;
inline void tidy(){
x=y=len=0;
}
inline friend St operator+(const St a,const St b){
St ans;
ans.x=a.x*f[b.len]+b.x;
ans.y=b.y*f[a.len]+a.y;
ans.len=a.len+b.len;
return ans;
}
}F;
class Tree{
public:
struct Node{
int l,r;
St sum;
}X[N<<2];
inline void pushup(int k){
X[k].sum=X[k<<1].sum+X[k<<1|1].sum;
}
inline void build(int k,int l,int r){
X[k].sum.tidy();
X[k].l=l,X[k].r=r;
X[k].sum.len=r-l+1;
if(l==r){
X[k].sum.x=X[k].sum.y=h[0];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
inline void add(int k,int i){
if(X[k].l==i&&i==X[k].r){
X[k].sum.x=X[k].sum.y=h[1];
return ;
}
int mid=(X[k].l+X[k].r)>>1;
if(i<=mid)
add(k<<1,i);
else
add(k<<1|1,i);
pushup(k);
}
inline St query(int k,int l,int r){
if(X[k].l==l&&r==X[k].r)
return X[k].sum;
int mid=(X[k].l+X[k].r)>>1;
if(r<=mid)
return query(k<<1,l,r);
else if(l>mid)
return query(k<<1|1,l,r);
else
return query(k<<1,l,mid)+query(k<<1|1,mid+1,r);
}
}Tr;
inline void init(){
h[0]=R(),h[1]=R();
f[0]=1;
For(i,1,N-1)
f[i]=f[i-1]*base;
}
inline void solve(){
ans=0;
n=read();
Tr.build(1,1,n);
For(i,1,n){
x=read();
Tr.add(1,x);
if(x<=n-x+1){
l=1,r=(x<<1ll)-1;
F=Tr.query(1,l,r);
}
else{
l=(x<<1ll)-n,r=n;
F=Tr.query(1,l,r);
}
if(F.x!=F.y)
ans=1;
}
if(ans)
puts("Y");
else
puts("N");
}
bool End;
int main(){
init();
T=read();
while(T--)
solve();
//cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}
CF452F Permutation
#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
#define For(i,l,r) for(int i=l;i<=r;i++)
#define _For(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=3e5+10;
const ull base=127;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
mt19937_64 R(time(0));
int T,n,x,l,r;
bool ans;
ull h[2],f[N];
class St{
public:
ull x,y;
int len;
inline void tidy(){
x=y=len=0;
}
inline friend St operator+(const St a,const St b){
St ans;
ans.x=a.x*f[b.len]+b.x;
ans.y=b.y*f[a.len]+a.y;
ans.len=a.len+b.len;
return ans;
}
}F;
class Tree{
public:
struct Node{
int l,r;
St sum;
}X[N<<2];
inline void pushup(int k){
X[k].sum=X[k<<1].sum+X[k<<1|1].sum;
}
inline void build(int k,int l,int r){
X[k].sum.tidy();
X[k].l=l,X[k].r=r;
X[k].sum.len=r-l+1;
if(l==r){
X[k].sum.x=X[k].sum.y=h[0];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
inline void add(int k,int i){
if(X[k].l==i&&i==X[k].r){
X[k].sum.x=X[k].sum.y=h[1];
return ;
}
int mid=(X[k].l+X[k].r)>>1;
if(i<=mid)
add(k<<1,i);
else
add(k<<1|1,i);
pushup(k);
}
inline St query(int k,int l,int r){
if(X[k].l==l&&r==X[k].r)
return X[k].sum;
int mid=(X[k].l+X[k].r)>>1;
if(r<=mid)
return query(k<<1,l,r);
else if(l>mid)
return query(k<<1|1,l,r);
else
return query(k<<1,l,mid)+query(k<<1|1,mid+1,r);
}
}Tr;
inline void init(){
h[0]=R(),h[1]=R();
f[0]=1;
For(i,1,N-1)
f[i]=f[i-1]*base;
}
inline void solve(){
ans=0;
n=read();
Tr.build(1,1,n);
For(i,1,n){
x=read();
Tr.add(1,x);
if(x<=n-x+1){
l=1,r=(x<<1ll)-1;
F=Tr.query(1,l,r);
}
else{
l=(x<<1ll)-n,r=n;
F=Tr.query(1,l,r);
}
if(F.x!=F.y)
ans=1;
}
if(ans)
puts("YES");
else
puts("NO");
}
bool End;
int main(){
init();
T=1;
while(T--)
solve();
//cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}