码迷,mamicode.com
首页 > 其他好文 > 详细

【单调队列优化】旅行问题

时间:2021-05-23 23:51:54      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:front   顺时针   出现   单调队列   include   队列   题目   前缀和   没有   

题目

一个环形公路上总共有N个车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米。
从某个车站出发,一直按顺时针(或逆时针)方向走遍所有的车站,并回到起点。
在一开始的时候,汽车内油量为零,每到一个车站就把该站所有的油都带上(起点站亦是如此),行驶过程中不能出现没有油的情况。
判断以每个车站为起点能否按条件成功周游一周。

思路

每个站油量减去到下一个站的距离即每个站的净得油量。
进行前缀和可以求出到这个站累计用油量。
每个环中,判断这个区间的最小累计用油量是否为负数(即不满足条件)。
对于多个起点,发现所求前缀和是一个编号累加的东西,可以用单调队列优化。

代码

#include <deque>
#include <cstdio>
#define int long long

std::deque<int> q;
int n;
int b[2000001], a[2000001], ans[2000001];

signed main() {
	scanf("%lld", &n);
	for (int i = 1, x, y; i <= n; i++) {
		scanf("%lld %lld", &x, &y);
		a[i + n] = a[i] = x - y;
		int d = n - i == 0 ? n : n - i;
		b[d + n] = b[d] -= y;
		b[2 * n - i + 1] = b[n - i + 1] += x;
	}
	for (int i = 2; i <= n * 2; i++)
		a[i] += a[i - 1], b[i] += b[i - 1];
	for (int i = 1; i < n * 2; i++) {
		while (q.size() && i - q.front() + 1 > n)
			q.pop_front();
		while (q.size() && a[i] <= a[q.back()])
			q.pop_back();
		q.push_back(i);
		if (i >= n) {
			if (a[q.front()] - a[i - n] >= 0)
				ans[i - n + 1] = 1;
		}
	}
	q.clear();
	for (int i = 1; i < n * 2; i++) {
		while (q.size() && i - q.front() + 1 > n)
			q.pop_front();
		while (q.size() && b[i] <= b[q.back()])
			q.pop_back();
		q.push_back(i);
		if (i >= n) {
			if (b[q.front()] - b[i - n] >= 0)
				ans[2 * n - i] = 1;
		}
	}
	for (int i = 1; i <= n; i++)
		if (ans[i])
			printf("TAK\n");
		else
			printf("NIE\n");
}

【单调队列优化】旅行问题

标签:front   顺时针   出现   单调队列   include   队列   题目   前缀和   没有   

原文地址:https://www.cnblogs.com/HSZGB/p/14728819.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!