当前位置: 首页 > 工具软件 > FEAST > 使用案例 >

P4085 [USACO17DEC]Haybale Feast G

梁烨烨
2023-12-01

知识点:尺取法,单调队列

难度:5

这个题的难度感觉高了,给个4应该比较合理,这种题看上去有很多做法,各种数据结构好像都行,我用的是我一眼看上去的方法,首先的想法就是尺取,对第一个区间进行尺取,但是我们还要维护和第一个序列相同的区间的第二个序列的最值,一开始想着用st表,但是我不会,看了看题解,发现可以使用单调队列

做了这个题对单调队列的理解又深了一点,单调队列不只是能解决之前固定滑动窗口最值的问题,我们这个问题只有一个窗口,大小是可以变的,单调队列同样可以来维护这个区间的最值,因为这里只需要它来维护这一个区间,就是我们尺取的区间,就算窗口怎么变,单调队列出队,入队的操作什么的都还是和原来一样的,只要是连续的窗口,那么就可以用单调队列来维护,今天是第一次这么用单调队列,打破了思维的束缚

总的思路就是我们用尺取法在第一个序列上面,用单调队列维护第二个序列的最值,区间就是尺取的区间,然后仅有的难度就是尺取的写法了,这里一旦第一个序列的区间和大于等于m,那么我们就要退出了,因为它要的是区间最大值最小能有多少,多加进去元素不会使答案变的更好,反而可能使答案变差,所以这就是尺取的写法

看了看题解,可以用二分,可以用各种数据结构,但是我觉得我这个方法算是不错的了,还有就是需要注意溢出的问题

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5;

int main() {
	int n;
	long long m;
	cin >> n >> m;
	int a[N], b[N];
	for (int i = 1; i <= n; i++) {
		cin >> a[i] >> b[i];
	}
	int l = 1, r = 1;
	long long sum = 0;
	int ans = 1e9;
	deque<int> q;
	while (true) {
		while (r <= n && sum < m) {
			while (!q.empty() && b[r] >= b[q.back()]) q.pop_back();
			q.push_back(r);
			sum += (long long) a[r++];
		}
		if (sum < m) break;
		while (l <= n && sum >= m) {
			ans = min(ans, b[q.front()]);
			if (!q.empty() && q.front() == l) q.pop_front();
			sum -= (long long) a[l++];
		}
	}
	cout << ans;
	return 0;
}

 类似资料:

相关阅读

相关文章

相关问答