Codeforces Round 973 (Div. 2)

EternalEpic發表於2024-09-21

今天這場沒準備打的,但是lbw打,我就倒開看看題目了。非常意外的是這場只要做到E就可以100名,而我感覺除了F都是垃圾題。

D. Minimize the Difference

這種求極差的題目很常規,由他那個操作可以看出單調性。故可以兩遍二分分別求最小值的最大值和最大值的最小值然後做差,也可以用單調棧去做。

const int N = 2e5 + 5;
int T, n; ll a[N];

inline bool check(ll x) {
	ll sum = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] > x) sum += a[i] - x;
		if (a[i] < x) {
			if (x - a[i] > sum) return false;
			sum -= x - a[i];
		}
	} return true;
}

inline bool checkII(ll x) {
	ll sum = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] > x) sum += a[i] - x;
		if (a[i] < x) sum -= x - a[i], sum = max(sum, 0ll);
	}
	
	if (sum > 0)  return false;
	return true;
}

signed main(void) {
	for (read(T); T; T--) {
		read(n); ll mx = 0, mn = 1ll << 62;
		for (int i = 1; i <= n; i++)
			read(a[i]), chkmax(mx, a[i]), chkmin(mn, a[i]);
		ll l = mn, r = mx, ans1 = l;
		while (l <= r) {
			ll mid = l + r >> 1;
			if (check(mid)) ans1 = mid, l = mid + 1;
			else r = mid - 1;
		}
		l = mn, r = mx; ll ans2 = r;
		while (l <= r) {
			ll mid = l + r >> 1;
			if (checkII(mid)) ans2 = mid, r = mid - 1;
			else l = mid + 1;
		}
//		writeln(ans1, ' '); writeln(ans2);
		writeln(ans2 - ans1);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

E. Prefix GCD

我們知道在gcd變小的過程中至少要除以二,則gcd收斂的次數是log級別的。故可以貪心找每次填入後字首gcd最小的數,時間複雜度 \(O(n\log(A))\)

inline int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}

const int N = 1e5 + 5;
int T, n, a[N];

signed main(void) {
	for (read(T); T; T--) {
		read(n);
		for (int i = 1; i <= n; i++) read(a[i]);
		if (n == 1) { writeln(a[1]); continue; }
		sort(a + 1, a + n + 1);
		int d = gcd(a[1], a[2]);
		for (int i = 3; i <= n; i++) d = gcd(d, a[i]);
		int D = a[1] / d, j = 1; ll ans = D;
		while (D > 1 && j < n) {
			int M = INT_MAX, k = j + 1;
			for (int i = j + 1; i <= n; i++)
				if (M > gcd(a[i] / d, D)) {
					M = gcd(a[i] / d, D);
					k = i;
				}
			ans += M; swap(a[j + 1], a[k]); D = M; j++;
//			writeln(D, ' '); writeln(j); 
		}
		
		ans += n - j;
		writeln(1ll * ans * d);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

相關文章