LOADING

加载过慢请开启缓存 浏览器默认开启

CF2050F Maximum modulo equality

一.题意

题目

给你一个长度为 $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;
}