P1890의 GCD 간격 세그먼트 트리

제목 설명

주어진 행 (\ N- \) 양수 \ (A [. 1] ... A [N-] \) .

\ (m의 \) 각각의 시간 간격의 쿼리 주어진 시간 쿼리 \ ([L, R & LT] \) , 출력 \ (a [L]의 .. [R]를 \) 최대 공약수이다.

입력 형식

두 정수의 첫 번째 행 (\ N-, m의 \) .

두 번째 행은 N 개의 정수를 나타내고, \ (A [이. 1] ... A [N] \) .

다음 \ (m의 \) 열의 각 행 \ (2 \) 종료점 심문 간격에 대해 나타내는 정수.

입력 데이터가 유효한지 확인.

출력 형식

공동 m 라인은 각 라인은 질문에 대한 답변을 나타냅니다.

샘플 입출력

입력 # 1

5 3
4 12 3 6 7
1 3
2 3
5 5

출력 # 1

1
3
7

설명 / 팁

데이터의 30 %, \ (N - <= 100, m <= 10 \)

데이터의 60 %, \ (m <= 1000 \)

데이터의 100 % \ (1 <= N -. <= 1000,1 <= m <= 1,000,000 \)

 0 < 数字大小 <= 1,000,000,000

해결 방법 :

여기에 기록 된 세그먼트 트리 구조 포인터가 제공된다 :

이 문제를 해결하려면, 먼저 알고 있어야합니다 \ (GCD의 \)를 유클리드 알고리즘에서 본 찾기위한 방법을 :

int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }

둘째, \ (GCD는 \) , 즉, 부 가산을 만족시킨다 :
[GCD (L, R & LT)가 [L, R5에서 GCD. (GCD (L, K) GCD (K + 1, R & LT)) K \를 = \ ] \]
세그먼트 트리 유지 관리를 직접 할 수 있습니다 ...

암호:

#include <iostream>
#include <cstdio>
using namespace std;
int read() {
    int x = 0, f = 1; char ch;
    while(! isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(x = ch^48; isdigit(ch = getchar()); x = (x<<3) + (x<<1) + (ch^48));
    return x * f;
}
int n, m;
inline int gcdd(int x, int y) { return y == 0 ? x : gcdd(y, x % y); }
struct Segment {
    struct node {
        int l, r, gc;
        node* ch[2];
        node(int l, int r, int gc) : l(l), r(r), gc(gc) {}
        inline int mid() { return (l + r) >> 1; }
        inline void up() { gc = gcdd(ch[0]->gc, ch[1]->gc); }
    } *root;
    void build(node *&o, int l, int r) {
        o = new node (l, r, 0);
        if(l == r) { o->gc = read(); return; }
        build(o->ch[0], l, o->mid());
        build(o->ch[1], o->mid()+1, r);
        o->up();
    }
    int query(node *o, int l, int r) {
        if(l <= o->l && o->r <= r) return o->gc;
        int res = 0;
        if(o->mid() >= l) res = query(o->ch[0], l, r);
        if(o->mid() < r) res = gcdd(res, query(o->ch[1], l, r));
        return res;
    }
} tr;
int main() {
    n = read(); m = read();
    tr.build(tr.root, 1, n);
    for(int i = 1, l, r; i <= m; ++ i) {
        l = read(); r =  read();
        printf("%d\n", tr.query(tr.root, l, r));
    }
    return 0;
}

추천

출처www.cnblogs.com/Paranoid-LS/p/11582701.html