Codecraft-18 and Codeforces Round_D.Bash and a Tough Math Pzle(線分樹)


D.Bash and a Tough Math Pzle
time limit per test
2.5 seconds
memory limit per test
256 megabytes
input
standard input
out put
スタンダードアウト
Bash likes playing with arrays.He has an array a 1,̵a2,̵… an 保存先 n integers.He likes to gess the greatest common divisor(gcd)of different segments of the array.Of course,sometimes the gess not corect.However,Bash will be satisfied if almost corect.
Suppose he gusess that the gcd of the elemens in the range [l,̵r] 保存先 a. is x.He considers the gess to be almost corect if he can change at most one element in the segment such that the gcd of the segment is x after making t he change.Note that when he gess,he doesn't actually change the array-he just wonders the gcd of the segment can be made x.Appt from this、he also sometimes makes changes to the array itself.
Since he can't figure it out hiself,Bash wants you to tell hich of his gess are almost corect.Formally,you have to process qqueries of one of the follwing forms:
1̵l?r?x — バッシュグレスthat the gcd of the range [l,̵r] is x.Report if this guss almost corect.2?i?y — Bash sets ai ト y.ノート: The array is 1-indexed.
Input
The first line contains an integer n (1̵≦̵n?≦?5・105) — the size of the array.
The second line contains n integers a 1,̵a2,̵…,?an (1̵≦̵ai̵≦?109) — the elemens of the array.
The third line contains an integer q (1̵≦̵q?≦?4・105) — the number of queries.
The next q lines describe the queries and may have one of the follwing forms:
1̵l?r?x (1̵≦̵l?≦r?r≦?n,?1?1?x≤?109)2?i?y (1̵≦̵i?≦?n,?1?1̵≦?y?109).Garanted、that there ist at least one query of first type.
Output
For each query of first type,output YES (without quot tes)if Bash's guss is almost corect and 「NO」 (without quot tes)otherswise.
Examples
input
3
2 6 3
4
1 1 2 2
1 1 3 3
2 1 9
1 1 3 2
out put
YES
YES
NO
input
5
1 2 3 4 5
6
1 1 4 2
2 3 6
1 1 4 2
1 1 5 2
2 5 10
1 1 5 2
out put
NO
YES
NO
YES
ノート
In the first sample,the ary initially is {2,̵6,̵3}
For query 1,the first two numbers already have their gcd as 2.
For query 2,we can achieve a gcd of 3 by change the first element of the array to 3.Note that the changes made during queries of type 1 are temporary and do not get refreted in the array.
After query 3,the array is now {9,̵6,̵3}
For query 4,no mater which element you change,you cannot get the gcd of the range to be 2.
#include 
using namespace std;
int a[500005];
struct tree{
	int l, r, v;
}c[500005 * 3];
vectorg;
int gcd(int a, int b){
	return b == 0 ? a : gcd(b, a % b);
}
void build(int o, int l, int r){
	c[o].l = l; c[o].r = r;
	if(l == r){
		c[o].v = a[l]; return;
	}
	int mid = l + r >> 1;
	build(o << 1, l, mid);
	build(o << 1 | 1, mid + 1, r);
	c[o].v = gcd(c[o << 1].v, c[o << 1 | 1].v);
}
void update(int o, int pos, int v){
	if(c[o].l == c[o].r){
		c[o].v = v; return;
	}
	int mid = c[o].l + c[o].r >> 1;
	if(pos <= mid) update(o << 1, pos, v);
	else update(o << 1 | 1, pos, v);
	c[o].v = gcd(c[o << 1].v, c[o << 1 | 1].v);
}
void query(int o, int L, int R){
	if(c[o].l >= L && c[o].r <= R){
		g.push_back(o); return;
	}
	int mid = c[o].l + c[o].r >> 1;
	if(mid >= L) query(o << 1, L, R);
	if(mid < R) query(o << 1 | 1, L, R);
}
bool check(int o, int v){
	if(c[o].l == c[o].r){
		return 1;
	}
	int mid = c[o].l + c[o].r >> 1;
	if(c[o << 1].v % v != 0 && c[o << 1 | 1].v % v != 0){
		return false;
	}
	if(c[o << 1].l == c[o << 1].r){
		if(c[o << 1].v % v == 0 || c[o << 1 | 1].v % v == 0){
			return true;
		}
		else{
			return false;
		}
	}
	if(c[o << 1].v % v != 0){
		return check(o << 1, v);
	}
	else{
		return check(o << 1 | 1, v);
	}
}
int main(){
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%d", &a[i]);
	}
	build(1, 1, n);
	int q, op, x, y, v, l, r, mid;;
	scanf("%d", &q);
	while(q--){
		scanf("%d", &op);
		if(op == 2){
			scanf("%d %d", &x, &y);
			update(1, x, y);
		}
		if(op == 1){
			scanf("%d %d %d", &x, &y, &v);
			g.clear();
			query(1, x, y);
			int cnt = 0, pos;
			for(int i = 0; i < g.size(); ++i){
				if(c[g[i]].v % v != 0){
					cnt++;
					pos = g[i];
				}
			}
			if(cnt == 0) printf("YES
"); if(cnt > 1) printf("NO
"); if(cnt == 1){ if(check(pos, v)) printf("YES
"); else printf("NO
"); } } } } /* : 5e5 ,4e5 , [l,r] GCD v( , ), 。 : gcd, 。 , , v, 。 , gcd v, NO, 。 */