一.题意
题目
给你一个长度为 $n$ 的数组 $a$ 和 $q$ 查询 $l$ , $r$ .
请为每个查询找出最大可能的 $m$ ,使得所有元素 $a_l$ , $a_{l+1}$ , …, $a_r$ 都等于 $m$ 的模。换句话说, $a_l \bmod m = a_{l+1} \bmod m = \dots = a_r \bmod m$ ,其中 $a \bmod b$ - 是 $a$ 除以 $b$ 的余数。特别的,当 $m$ 可以是无限大时,请打印 $0$ 。
输入
第一行包含一个整数 $t$ ( $1 \le t \le 10^4$ )–测试用例数。( $1 \le t \le 10^4$ ) - 测试用例的数量。
每个测试用例的第一行包含两个整数 $n$ , $q$ ( $1 \le n, q \le 2\cdot 10^5$ ) - 数组长度和查询次数。
每个测试用例的第二行包含 $n$ 个整数 $a_i$ ( $1 \le a_i \le 10^9$ ) - 数组的元素。
在每个测试用例的后续 $q$ 行中,提供了两个整数 $l$ , $r$ ( $1 \le l \le r \le n$ )–查询范围。
保证所有测试用例中 $n$ 的总和不超过 $2\cdot 10^5$ , $q$ 的总和不超过 $2\cdot 10^5$ 。
二.思路
若一个区间内所有数字对m同余,那这些数字在减去余数后,该区间的GCD应等于m,那么反过来若想求m的值,只需对该区间求差值,并维护差值的gcd即可,k可以使用线段树中的区间查询功能完成维护gcd,以下是完整代码
三.代码实现
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int N = 4e5+10;
struct tree{
int val;
int l,r,sum;
}tr[N*4];
int a[N],b[N];
void pushup(int p){
tr[p].val=__gcd(tr[p*2].val,tr[p*2+1].val);
}
void build(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
if(l==r){
tr[p].val=a[r];
return;
}
int mid=l+r>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
pushup(p);
}
int query(int p,int l,int r,int ql,int qr){
if(ql==l&&qr==r){
return tr[p].val;
}
int mid=l+r>>1;
if(qr<=mid) return query(p*2,l,mid,ql,qr);
else if(ql>mid) return query(p*2+1,mid+1,r,ql,qr);
else return __gcd(query(p*2,l,mid,ql,mid),query(p*2+1,mid+1,r,mid+1,qr));
}
void solve() {
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>b[i];
a[i]=abs(b[i]-b[i-1]);
}
build(1,1,n);
while(q--){
int l,r;
cin>>l>>r;
if(l==r){
cout<<0<<' ';
continue;
}
cout<<query(1,1,n,l+1,r)<<' ';
}
cout<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}