日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2124 等差子序列 线段树维护哈希

發布時間:2024/7/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2124 等差子序列 线段树维护哈希 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

$ \Rightarrow $ 戳我進BZOJ原題

等差子序列 Time Limit: 3 Sec $ \quad $ Memory Limit: 259 MB  

Description

給一個 $ 1 $ 到 $ N $ 的排列 $ (A_i) $ ,詢問是否存在 $ 1 \le p_1<p_2<p_3<p_4<p_5<…<p_ \le N (Len \ge 3) $ , 使得 $ A_,A_,A_,…A_{p_}是一個等差序列。  

Input

輸入的第一行包含一個整數 $ T $ ,表示組數。 接下來 $ T $ 組數據,每組第一行一個整數 $ N $ ,每組第二行為一個 $ 1 $ 到 $ N $ 的排列,數字兩兩之間用空格隔開。 $ N \le 10000,T \le 7 $  

Output

對于每組數據,如果存在一個等差子序列,則輸出一行“Y”,否則輸出一行“N”。  

Sample Input

231 3 233 2 1

###Sample Output

NY

 

思路

  • 題目是要找 $ i<j<k $ ,使得 $ A_j - A_i = A_k - A_j $ ;

  • 我們考慮按順序插入 $ (A_i) $ ,對于我們當前位置 $ j $ ,如果有一個 $ A_i $ 已經出現了, 但是 $ A_k $ 還沒有出現,因為是排列,所以這個 $ A_k $ 必然在后面,所以答案為“Y”;

  • 我們用一個輔助數組 $ (B_i) $ ,按順序如果 $ x $ 出現了,就標記為 $ 1 $ , 那么如果一個數 $ x $ 滿足條件,那么必然有 $ B_ != B_{x+y} $ , 那么只需要判斷以 $ x $ 為中心的最長的字符串是否為回文串即可;

  • 因為如果不是回文串那么必然能找到一個 $ B_ != B_{x+y} $ ,所以答案為“Y”, 判斷回文串可以用正反兩邊 $ hash $ ,然后 $ hash $ 值要動態修改,所以用樹狀數組和線段樹都可以;  

代碼

/**************************************************************Problem: 2124User: PotremZLanguage: C++Result: AcceptedTime:2480 msMemory:2072 kb ****************************************************************/#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define int long long #define Mod 1000000007 #define N 10005 inline int read() {register char ch;while(!isdigit(ch=getchar()));register int x=ch^'0';while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');return x; } int T,n,a[N],hash1[N<<2],hash2[N<<2],pows[N]; inline void pushup(int o,int len){int mid=len>>1;hash1[o]=(hash1[o<<1]*pows[mid]%Mod+hash1[o<<1|1])%Mod;hash2[o]=(hash2[o<<1]+hash2[o<<1|1]*pows[len-mid]%Mod)%Mod; } void updata(int o,int l,int r,int pos){if(l==r){hash1[o]=hash2[o]=1;return;}int mid=l+r>>1;if(pos<=mid) updata(o<<1,l,mid,pos);else updata(o<<1|1,mid+1,r,pos);pushup(o,r-l+1); } int query1(int o,int l,int r,int L,int R){if(L>R) return 0;if(L==l&&r==R) return hash1[o];int mid=l+r>>1;if(L>mid) return query1(o<<1|1,mid+1,r,L,R);else if(R<=mid) return query1(o<<1,l,mid,L,R);else return (query1(o<<1,l,mid,L,mid)*pows[R-mid]%Mod+query1(o<<1|1,mid+1,r,mid+1,R))%Mod; } int query2(int o,int l,int r,int L,int R){if(L>R) return 0;if(L==l&&r==R) return hash2[o];int mid=l+r>>1;if(L>mid) return query2(o<<1|1,mid+1,r,L,R);else if(R<=mid) return query2(o<<1,l,mid,L,R);else return (query2(o<<1,l,mid,L,mid)+query2(o<<1|1,mid+1,r,mid+1,R)*pows[mid-L+1]%Mod)%Mod; } signed main(){T=read(); pows[0]=1;for(int i=1;i<N;++i) pows[i]=(pows[i-1]<<1)%Mod;while(T--){n=read(); bool f=0;memset(hash1,0,sizeof(hash1));memset(hash2,0,sizeof(hash2));for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=n;++i){int len=min(n-a[i],a[i]-1);if(query1(1,1,n,a[i]-len,a[i]-1)!=query2(1,1,n,a[i]+1,a[i]+len)){ puts("Y"); break;}updata(1,1,n,a[i]);if(i==n) puts("N");}}return 0; }

轉載于:https://www.cnblogs.com/PotremZ/p/9662973.html

總結

以上是生活随笔為你收集整理的BZOJ 2124 等差子序列 线段树维护哈希的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。