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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

等差区间 线段树+GCD

發布時間:2023/12/3 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 等差区间 线段树+GCD 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

已知一個長度為?nn?的數組?a[1],a[2],,a[n]a[1],a[2],…,a[n],我們進行?qq?次詢問,每次詢問區間?a[l],a[l+1],,a[r?1],a[r]a[l],a[l+1],…,a[r?1],a[r],數字從小到大排列后,是否會形成等差數列。等差數列的定義為,數列相鄰兩項(后一項減去前一項)的差值相等。

Input

本題有多組輸入數據。

每組輸入數據第一行輸入兩個正整數?nn?和?qq。第二行輸入?nn?個正整數?a[1],a[2],,a[n]a[1],a[2],…,a[n]。最后輸入?qq?行,每行兩個數字?l,rl,r1lrn1≤l≤r≤n),表示詢問區間?a[l],,a[r]a[l],…,a[r]

1n,q105,1a[i]1061≤n,q≤105,1≤a[i]≤106

Output

對于每組詢問輸出一行,如果形成等差數列,輸出“Yes ”,否則輸出“No”(不含引號)。

Sample Input

5 5 3 1 5 2 4 1 3 4 5 1 4 3 4 2 2

Sample Output

Yes Yes No Yes Yes 題目大意:給定一個數列,并給出很多區間詢問,問是否是等差數列。題解:這道題目用了一個很好的判斷等差數列的思想,首先如果區間內最大值與最小值相同,那么一定是等差數列不然的話,判斷區間和與(max+min)*n/2是否相等,如不相等那么輸出No,否則再判斷區間gcd,如果是等差數列那么它的區間gcd應該等于其公差(這里是我覺得最精華的地方),而公差我們可以用(max-min)/(n-1)來計算得到 其中區間最值用線段樹維護,區間gcd也用線段樹維護 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define int long long const int MAX = 1e5+6; const int INF = 1e9; int n,q; int A[MAX]; int stmax[MAX<<2]; int stgcd[MAX<<2]; int stmin[MAX<<2]; int sum[MAX]; int gcd(int a,int b) {if(b == 0) return a;return gcd(b,a % b); } void init(int v,int l,int r) {if(r - l == 1){stmax[v] = stmin[v] = A[l];stgcd[v] = abs(A[l+1]-A[l]);}else{init(2*v+1,l,(l+r)/2);init(2*v+2,(l+r)/2,r);stmax[v] = max(stmax[2*v+1],stmax[2*v+2]);stmin[v] = min(stmin[2*v+1],stmin[2*v+2]);stgcd[v] = gcd(stgcd[2*v+1],stgcd[2*v+2]);} } int querymin(int v,int a,int b,int l,int r) {if(l <= a && r >= b) return stmin[v];else if(b <= l || r <= a) return INF;else return min(querymin(2*v+1,a,(a+b)/2,l,r),querymin(2*v+2,(a+b)/2,b,l,r)); } int querymax(int v,int a,int b,int l,int r) {if(l <= a && r >= b) return stmax[v];else if(b <= l || r <= a) return 0;else return max(querymax(2*v+1,a,(a+b)/2,l,r),querymax(2*v+2,(a+b)/2,b,l,r)); } int querygcd(int v,int a,int b,int l,int r) {if(l <= a && r >= b) return stgcd[v];else if(b <= l || r <= a) return 0;else return gcd(querygcd(2*v+1,a,(a+b)/2,l,r),querygcd(2*v+2,(a+b)/2,b,l,r)); } main() {while(~scanf("%lld%lld",&n,&q)){sum[0] = 0;for(int i = 0;i < n;i++){scanf(" %lld",&A[i]);sum[i+1] = sum[i] + A[i];}A[n] = A[n-1];init(0,0,n);for(int i = 0;i < q;++i){int l,r;scanf("%lld%lld",&l,&r);if(r - l <= 1) {puts("Yes");continue;}int mini = querymin(0,0,n,l-1,r);int maxi = querymax(0,0,n,l-1,r);if(maxi == mini) {puts("Yes");continue;}//cout<<r<<" "<<l-1<<endl;if((sum[r] - sum[l-1])*2 != (maxi + mini) * (r-l+1)){puts("No");continue;}int d = (maxi - mini) / (r - l);if((maxi-mini)%(r-l) == 0 && querygcd(0,0,n,l-1,r-1) == d) puts("Yes");else puts("No");}}return 0;}

總結

以上是生活随笔為你收集整理的等差区间 线段树+GCD的全部內容,希望文章能夠幫你解決所遇到的問題。

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