[ABC254F] Rectangle GCD 题解

[ABC254F] Rectangle GCD Solution

更好的阅读体验戳此进入

题面

给定序列 $ a_n, b_n $,存在 $ n \times n $ 的网格图,令图上 $ (i, j) $ 位置的值为 $ a_i + b_j \(。\) q $ 次询问给定 $ h_1, h_2, w_1, w_2 $,查询左上角为 $ (h_1, w_1) $,右下角为 $ (h_2, w_2) $ 的矩形中所有数的 $ \gcd $。

Solution

挺好的一道水题,有一道类似的题,AcWing 246 区间最大公约数,简而言之就是实现区间加,区间求 $ \gcd $。这道题也是类似的。

首先有一个性质,更相减损术,即 $ \gcd(a, b) = \gcd(a, b - a) $。然后我们尝试列举一个以 $ (i, j) $ 为左上角,$ (x, y) $ 为右下角的矩形:

$ a_{i} + b_{j} $ $ a_{i} + b_{j + 1} $ $ a_{i} + b_{j + 2} $ $ \cdots $ $ a_{i} + b_{y} $
$ a_{i + 1} + b_{j} $ $ a_{i + 1} + b_{j + 1} $ $ a_{i + 1} + b_{j + 2} $ $ \cdots $ $ a_{i + 1} + b_{y} $
$ a_{i + 2} + b_{j} $ $ a_{i + 2} + b_{j + 1} $ $ a_{i + 2} + b_{j + 2} $ $ \cdots $ $ a_{i + 2} + b_{y} $
$ \cdots $ $ \cdots $ $ \cdots $ $ \cdots $ $ \cdots $
$ a_{x} + b_{j} $ $ a_{x} + b_{j + 1} $ $ a_{x} + b_{j + 2} $ $ \cdots $ $ a_{x} + b_{y} $

然后不难发现可以通过更相减损术,对这个矩形横向进行差分:

$ a_{i} + b_{j} $ $ b_{j + 1} - b_j $ $ b_{j + 2} - b_{j + 1} $ $ \cdots $ $ b_{y} - b_{y - 1} $
$ a_{i + 1} + b_{j} $ $ b_{j + 1} - b_j $ $ b_{j + 2} - b_{j + 1} $ $ \cdots $ $ b_{y} - b_{y - 1} $
$ a_{i + 2} + b_{j} $ $ b_{j + 1} - b_j $ $ b_{j + 2} - b_{j + 1} $ $ \cdots $ $ b_{y} - b_{y - 1} $
$ \cdots $ $ \cdots $ $ \cdots $ $ \cdots $ $ \cdots $
$ a_{x} + b_{j} $ $ b_{j + 1} - b_j $ $ b_{j + 2} - b_{j + 1} $ $ \cdots $ $ b_{y} - b_{y - 1} $

发现除了最初始的位置,剩下的每一列都是相同的,所以我们不难想到,除了第一行第一列之外的数,会因为重复所以可以不用考虑。同时对于对应的第一列,也可以差分。最后就可以变成,对于一段查询,求的是序列 $ a $ 差分数组的 $ [w_1 + 1, w_2] $ 的 $ \gcd $,和序列 $ b $ 差分数组的 $ [h_1 + 1, h_2] $ 的 $ \gcd $,再和 $ a_{h_1} + b_{w_1} $ 做一下 $ \gcd $ 即可,记得判断 $ w_1 \neq w_2 $ 和 $ h_1 \neq h_2 $。

然后考虑如何快速维护区间的 $ \gcd $,这个东西也就可以直接挂在线段树上,或者因为没有修改,用 ST表 也行(不过我不喜欢 ST表,所以用的线段树维护)。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define MAXN (210000)

template < typename T = int >
inline T read(void);

int N, Q;
int A[MAXN], B[MAXN], dA[MAXN], dB[MAXN];

class SegTree{
private:
    int tr[MAXN << 2];
    #define LS (p << 1)
    #define RS (LS | 1)
    #define MID ((gl + gr) >> 1)
public:
    void Pushup(int p){tr[p] = __gcd(tr[LS], tr[RS]);}
    void Build(bool flag, int p = 1, int gl = 1, int gr = N){//true - line(y), false - row(x)
        if(gl == gr)return tr[p] = flag ? dB[gl] : dA[gl], void();
        Build(flag, LS, gl, MID), Build(flag, RS, MID + 1, gr);
        Pushup(p);
    }
    int Query(int l, int r, int p = 1, int gl = 1, int gr = N){
        if(l <= gl && gr <= r)return tr[p];
        if(r <= MID)return Query(l, r, LS, gl, MID);
        if(l >= MID + 1)return Query(l, r, RS, MID + 1, gr);
        return __gcd(Query(l, r, LS, gl, MID), Query(l, r, RS, MID + 1, gr));
    }
}stLine, stRow;

int main(){
    N = read(), Q = read();
    for(int i = 1; i <= N; ++i)A[i] = read(), dA[i] = A[i] - A[i - 1];
    for(int i = 1; i <= N; ++i)B[i] = read(), dB[i] = B[i] - B[i - 1];
    stLine.Build(true), stRow.Build(false);
    while(Q--){
        int h1 = read(), h2 = read(), w1 = read(), w2 = read();
        int ans = A[h1] + B[w1];
        if(w1 != w2)ans = __gcd(ans, stLine.Query(w1 + 1, w2));
        if(h1 != h2)ans = __gcd(ans, stRow.Query(h1 + 1, h2));
        printf("%d\n", abs(ans));
    }
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2022_12_06 初稿

posted @ 2023-01-07 15:34  Tsawke  阅读(40)  评论(0)    收藏  举报