【倍增】P3422 [POI2005]LOT-A Journey to Mars 题解

发布时间 2023-10-05 22:37:06作者: Pengzt

P3422

一道有点意思的题。

看到是一个环,先破环为链,即 \(a_{n+i}=a_i, b_{n+i}=b_i\),此时就只需要跳到 \(x+n\) 而无需判环了。

如果顺时针走:

\(sum_i = \sum\limits_{j=1}^{i}{a_j-b_j}\),当能从 \(x\) 跳到 \(x+n\) 时,有

\[sum_{x-1} \le sum_x, sum_{x-1} \le sum_{x+1}, \dots, sum_{x-1} \le sum_{x+n-1} \]

变形一下:

\[sum_{x-1} \le \min\limits_{x \le i < x+n}\{sum_i\} \]

求长度不变区间的最小值,可以使用单调队列。

逆时针就反着再做一遍。

代码:

const int N = 1e6 + 5;
int n, hd, tl; 
int a[N << 1], b[N << 1], c[N << 1], q[N << 1];
int ta[N], tb[N], ans[N], flag[N];
ll s[N << 1];

void solve() {
	for (int i = 1; i <= n; i++) s[i] = s[i - 1] + c[i];
	for (int i = 1; i <= n; i++) s[i + n] = s[i + n - 1] + c[i];
	for (int i = 1, hd = 1, tl = 0; i <= n * 2; i++) {
		if (hd <= tl && q[hd] < i - n + 1) hd++;
		while (hd <= tl && s[q[tl]] >= s[i]) tl--;
		q[++tl] = i;
		if (i >= n)
			ans[i - n + 1] = s[q[hd]];
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cin >> n;
	for (int i = 1; i <= n; i++) {
		std::cin >> a[i] >> b[i];
		a[i + n] = a[i], b[i + n] = b[i];
		c[i + n] = c[i] = a[i] - b[i];
	}
	solve();
	for (int i = 1; i <= n; i++)
		if (ans[i] >= s[i - 1])
			flag[i] = 1;
	for (int i = 1; i <= n; i++)
		c[i] = a[n - i + 1] - b[((n - i ? n - i : n))];
	solve();
	for (int i = 1; i <= n; i++)
		if (ans[i] >= s[i - 1])
			flag[n - i + 1] = 1;
	for (int i = 1; i <= n; i++)
		std::cout << (flag[i] ? "TAK" : "NIE") << "\n";
	return 0;
}