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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

codevs 1283 等差子序列

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

http://codevs.cn/problem/1283/

題目描述?Description

給一個 1 到 N 的排列{Ai},詢問是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len>=3),使得 Ap1,Ap2,Ap3,…ApLen?是一個等差序列。

輸入描述?Input Description

輸入的第一行包含一個整數 T,表示組數。

?下接 T 組數據,每組第一行一個整數 N,每組第二行為一個 1 到 N 的排列, 數字兩兩之間用空格隔開。

輸出描述?Output Description

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

樣例輸入?Sample Input

2

3

1 3 2

3

3 2 1

樣例輸出?Sample Output

N

Y

數據范圍及提示?Data Size & Hint

對于5%的數據,N<=100,對于30%的數據,N<=1000,對于100%的數據,N<=10000,T<=7

?

線段樹+hash

首先要注意的是這個排列是1到n的排列

然后當然是找3個數形成等差子序列

暴力:枚舉中間的數,枚舉左邊的數,枚舉右邊的數,看是否滿足 2*mid=l+r

O(n3)

繼續想,因為保證排列是1到n

所以對于一個數x,若以x為mid能形成等差子序列,那么另外兩個數一定在x兩側

即從左往右枚舉,當枚舉到mid時,能早就枚舉到了l,不能枚舉到r

可以用0,1表示這個數是否被枚舉到

舉個例子:

3 6 1 2 4 5

當枚舉到第5個數4時,0 1序列為

1 1 1 1 0 1

4的左邊分別是1和0,說明枚舉到4時,3已經被枚舉到了,5還沒有被枚舉

但這樣仍然要枚舉,沒有減少時間復雜度

如何去掉枚舉的過程?

繼續想,發現我們要比較的是mid左右的兩個對稱區間

舉個例子:

1 8 3 6 5 7 4 2

當枚舉到3時,0 1序列為:

1 0 1 0 0 0 0 1

我們實際需要的是判斷2和4的01序列是否相等,1和5的01序列是否相等

因為是對稱的

可以轉化為判斷區間[1,2]和區間[5,4](注意這里是[5,4],不是[4,5])是否相等

線段樹維護區間正序哈希值和倒序哈希值,即可log判斷

總復雜度:O(nlogn)

#include<cstdio> #include<cstring> #include<algorithm> #define N 10001 #define LL unsigned long long using namespace std; int T,n,x,len; bool ok; LL bit[N],hash[N*4],anti_hash[N*4],r1,r2; struct TREE {public:void up(int k,int l,int r){hash[k]=hash[k<<1]*bit[r-(l+r>>1)]+hash[k<<1|1];anti_hash[k]=anti_hash[k<<1|1]*bit[(l+r>>1)-l+1]+anti_hash[k<<1];}void change(int k,int l,int r,int pos){if(l==r) {anti_hash[k]=hash[k]=1;return;}int mid=l+r>>1;if(pos<=mid) change(k<<1,l,mid,pos);else change(k<<1|1,mid+1,r,pos);up(k,l,r);}LL query(int k,int l,int r,int opl,int opr,int w){if(l>=opl&&r<=opr) return w==1 ? hash[k]:anti_hash[k];int mid=l+r>>1;if(opr<=mid) return query(k<<1,l,mid,opl,opr,w);else if(opl>mid) return query(k<<1|1,mid+1,r,opl,opr,w);else if(w==1) return query(k<<1,l,mid,opl,mid,w)*bit[opr-mid]+query(k<<1|1,mid+1,r,mid+1,opr,w);else return query(k<<1|1,mid+1,r,mid+1,opr,w)*bit[mid-opl+1]+query(k<<1,l,mid,opl,mid,w);}void solve(int i){len=min(i-1,n-i);r1=query(1,1,n,i-len,i-1,1);r2=query(1,1,n,i+1,i+len,2);if(r1!=r2) ok=true;} }tree; int main() {bit[1]=233; for(int i=2;i<N;i++) bit[i]=bit[i-1]*233;scanf("%d",&T);while(T--){memset(hash,0,sizeof(hash));memset(anti_hash,0,sizeof(anti_hash));scanf("%d",&n);ok=false;for(int i=1;i<=n;i++){scanf("%d",&x);if(!ok){tree.change(1,1,n,x);if(x!=1&&x!=n) tree.solve(x);}}if(ok) puts("Y");else puts("N");} }

?

轉載于:https://www.cnblogs.com/TheRoadToTheGold/p/6813049.html

總結

以上是生活随笔為你收集整理的codevs 1283 等差子序列的全部內容,希望文章能夠幫你解決所遇到的問題。

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