P2757 [國家集訓隊] 等差子序列 與 CF452F Permutation

rgw2010發表於2024-08-26

題意:

給定一個長度為 \(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;
}

相關文章