Garlic Counting - Maximum Common Number

Keywords: less Java

I. content


Two, train of thought

  • The gcd value of each interval is maintained by the segment tree, and the gcd of a single point is itself.
  • Because the title "Coconut Girl" can modify one of them (but the value of itself remains unchanged, when the calculation is considered to be modified) we only need to calculate a number of gcd multiples that are not given by Coconut Girl, if the number is less than or equal to 1 then output yes, otherwise output no. Because when the number has a multiple of gcd that is not given by Coconut Girls, Coconut Girls can modify this number, so the output is yes.
  • When querying, query between partitions. If the value of an interval satisfies the multiple of Coconut Girl's gcd, then you don't need to look for this interval. If the number of left intervals is more than 2, then you don't need to look for the right interval. So it's O(lgn).

Three, code

import java.io.PrintWriter;
import java.util.Scanner;

public class H_Greatest common divisor {
	static int N = 500000;
	static int[] a = new int[N + 5];
	static int[] c = new int[N  * 4];//Maintenance interval gcd
	static int n, q, code, l, r, x, y, mod;
	static PrintWriter out = new PrintWriter(System.out);
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		for (int i = 1; i <= n; i++) {
			a[i] = sc.nextInt();
		}
		build(1, 1, n);
		q = sc.nextInt();
		for (int i = 1; i <= q; i++) {
			code = sc.nextInt();
			if (code == 1) {
				l = sc.nextInt();
				r = sc.nextInt();
				mod = sc.nextInt();
				if (query(1, 1, n, l, r, mod) <= 1) {
					System.out.println("yes");
				} else {
					System.out.println("no");
				}
			} else {
				x = sc.nextInt();
				y = sc.nextInt();
				update(1, 1, n, x, y);
			}
		}
		out.close();
	}
	static void build(int id, int l, int r) {
		if (l == r) {
			c[id] = a[l];
			return;
		}
		int mid = (l + r) >> 1;
		build(id << 1, l, mid);
		build(id << 1 | 1, mid + 1, r);		 
		c[id] = gcd(c[id << 1], c[id << 1 | 1]);
	}
	//Single point update
	static void update(int id, int l, int r, int x, int v) {
		if (l == r) {
			c[id] = v;
			return;
		}
		int mid = (l + r) >> 1;
		if (x <= mid) {
			update(id << 1, l, mid, x, v);
		} else {
			update(id << 1 | 1, mid + 1, r, x, v);
		}
		c[id] = gcd(c[id << 1], c[id << 1 | 1]);      
	}
	//Interval query to see if the number is less than or equal to 1, if less than or equal to 1, it satisfies yes or no
	static int query(int id, int l, int r, int x, int y, int mod) {
		if (l == r) {
			return c[id] % mod == 0 ? 0 : 1;
		}
		int mid = (l + r) >> 1;
		int ans = 0;
		//Seeing whether the gcd of the left interval is divisible does not mean that the number is not a multiple of the mode. Seeing how many are greater than two, then no directly. If only one is looking at how many are in the right interval.
		if (x <= mid && (c[id << 1] % mod != 0)) {
			ans += query(id << 1, l, mid, x, y, mod);
			if (ans >= 2) {
				return 2;
			}
		}
		if (y > mid && c[id << 1 | 1] % mod != 0) {
			ans += query(id << 1 | 1, mid + 1, r, x, y, mod);
			if (ans >= 2) {
				return 2; //Not satisfied with direct output no
			}
		}
		return ans;
	}
	static int gcd(int a, int b) {
		if (b == 0) 
			return a;
		return gcd(b, a % b);
	}
}

Posted by blankextacy on Fri, 04 Oct 2019 17:19:35 -0700