2016级算法第四次上机-G.ModricWang的序列问题 II

1021 ModricWang的序列问题II

思路

此题与上一题区别不是很大,只是增加了一个长度限制,当场通过的人数就少了很多。

大体解题过程与上一题相同。区别在于对(f[]) 的操作。没有长度限制的时候,(f[]) 的更新策略是立即更新。假设间隔为(T),现在由于需要考虑间隔,那么在处理第(i) 个元素的时候,就需要看到 前(i -T) 个元素生成的(f[]) ,而不能受到第(i-T+1)(i-1) 个元素的干扰。因此,考虑如下操作:每次准备更新(f[]) 时,先不要更新,记录下操作的内容,过(T) 步再进行操作,这样就可以让(f[]) 不再显示当前元素之前(T) 步的修改内容,每次更新都不受前(T) 步的影响,因此生成的序列中相邻元素的间隔都是不小于(T) 的。

代码

#include <iostream>
#include <queue>

using namespace std;

const int MAXN = 500010;
int nums[MAXN], pool[MAXN];

queue<pair<int, int>> buffer;

//用二分查找的方法找到一个位置,使得num>pool[i-1] 并且num<pool[i],并用num代替b[i]
int Search(int num, int low, int high) {
	int mid;
	while (low <= high) {
		mid = (low + high) / 2;
		if (num > pool[mid]) low = mid + 1;
		else high = mid - 1;
	}
	return low;
}

int DP(int n, int k) {
	while (!buffer.empty())buffer.pop();
	int i, len, pos;
	pool[1] = INT_MAX;
	len = 1;
	for (i = 1; i <= n; i++) {
		if (nums[i] > pool[len]) {   //如果a[i]比b[]数组中最大还大直接插入到后面即可
			buffer.emplace(nums[i], len + 1);
		} else {    //用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置
			pos = Search(nums[i], 1, len);
			buffer.emplace(nums[i], pos);
		}
		while (buffer.size() >= k) {
			if (buffer.front().second > len) {
				len = buffer.front().second;
				pool[buffer.front().second] = buffer.front().first;
			} else if (buffer.front().first < pool[buffer.front().second]) {
				pool[buffer.front().second] = buffer.front().first;
			}
			buffer.pop();
		}
	}
	while (!buffer.empty()) {
		if (buffer.front().second > len) {
			len = buffer.front().second;
			pool[buffer.front().second] = buffer.front().first;
		} else if (buffer.front().first < pool[buffer.front().second]) {
			pool[buffer.front().second] = buffer.front().first;
		}
		buffer.pop();
	}
	return len;
}



int main() {
	ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
		cin >> nums[i];
	cout << DP(n, k) << "
";
}
原文地址:https://www.cnblogs.com/AlvinZH/p/7978029.html