Розбір
To solve the problem, it is necessary to implement a segment tree that supports modification of a single element and computation of the Greatest Common Divisor (GCD) over a segment.
Algorithm realization
Let's declare an array to store the segment tree. We'll store the input sequence of numbers in the array . The segment tree supports the GCD operation. Since , the values in the cells of will not exceed the limits of the type.
#define MAX 1000001 vector<int> SegTree(4 * MAX, 0); vector<int> v;
Build a segment tree based on the array .
void BuildTree(vector<int> &a, int v, int lpos, int rpos) { if (lpos == rpos) SegTree[v] = a[lpos]; else { int mid = (lpos + rpos) / 2; BuildTree(a, 2 * v, lpos, mid); BuildTree(a, 2 * v + 1, mid + 1, rpos); SegTree[v] = gcd(SegTree[2 * v], SegTree[2 * v + 1]); } }
The GetGCD function returns the GCD over the segment .
The vertex corresponds to the segment .
int GetGCD(int v, int lpos, int rpos, int left, int right) { if (left > right) return 0; if ((left == lpos) && (right == rpos)) return SegTree[v]; int mid = (lpos + rpos) / 2; return gcd(GetGCD(2 * v, lpos, mid, left, min(right, mid)), GetGCD(2 * v + 1, mid + 1, rpos, max(left, mid + 1), right)); }
The Update function assigns the value to the element at index .
The vertex corresponds to the segment .
void update(int v, int lpos, int rpos, int pos, int val) { if (lpos == rpos) SegTree[v] = val; else { int mid = (lpos + rpos) / 2; if (pos <= mid) update(2 * v, lpos, mid, pos, val); else update(2 * v + 1, mid + 1, rpos, pos, val); SegTree[v] = gcd(SegTree[2 * v], SegTree[2 * v + 1]); } }
The main part of the program. Read the input sequence of numbers into the array , starting from the first index.
scanf("%d", &n); v.resize(n + 1); for (i = 1; i <= n; i++) scanf("%d", &v[i]);
Build the segment tree based on the elements of the array .
BuildTree(v,1,1,n);
Process the queries sequentially.
scanf("%d",&m); for(i = 0; i < m; i++) { scanf("%d %d %d",&q,&l,&r); if (q == 1) printf("%d\n",GetGCD(1,1,n,l,r)); else update(1,1,n,l,r); }
Python realization
import math
Declare a list to store the segment tree. The segment tree supports the GCD operation.
MAX = 1000001 SegTree = [0] * (4 * MAX)
Declare a function gcd that computes the GCD of two numbers.
def gcd(a, b): return math.gcd(a, b)
Build a segment tree based on the list .
def BuildTree(a, v, lpos, rpos): if lpos == rpos: SegTree[v] = a[lpos] else: mid = (lpos + rpos) // 2 BuildTree(a, 2 * v, lpos, mid) BuildTree(a, 2 * v + 1, mid + 1, rpos) SegTree[v] = gcd(SegTree[2 * v], SegTree[2 * v + 1])
The GetGCD function returns the GCD over the segment .
The vertex corresponds to the segment .
def GetGCD(v, lpos, rpos, left, right): if left > right: return 0 if left == lpos and right == rpos: return SegTree[v] mid = (lpos + rpos) // 2 return gcd(GetGCD(2 * v, lpos, mid, left, min(right, mid)), GetGCD(2 * v + 1, mid + 1, rpos, max(left, mid + 1),right))
The Update function assigns the value to the element at index .
The vertex corresponds to the segment .
def Update(v, lpos, rpos, pos, val): if lpos == rpos: SegTree[v] = val else: mid = (lpos + rpos) // 2 if pos <= mid: Update(2 * v, lpos, mid, pos, val) else: Update(2 * v + 1, mid + 1, rpos, pos, val) SegTree[v] = gcd(SegTree[2 * v], SegTree[2 * v + 1])
The main part of the program. Read the input sequence of numbers into the list , starting from the first index.
n = int(input()) v = [0] + list(map(int, input().split()))
Build the segment tree based on the elements of the list .
BuildTree(v, 1, 1, n)
Process the queries sequentially.
m = int(input()) for _ in range(m): q, l, r = map(int, input().split()) if q == 1: print(GetGCD(1, 1, n, l, r)) else: Update(1, 1, n, l, r)