제목 설명
주어진 행 (\ 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;
}