现在的位置: 首页 > 综合 > 正文

《算法竞赛-训练指南》第三章-3.8_UVa 11235

2013年10月11日 ⁄ 综合 ⁄ 共 1826字 ⁄ 字号 评论关闭

不是自己智商不够,而是自己不能钻进去,不能静下心来,学习新的知识点,其实这个信息竞赛和其他的竞赛也是一样的,知识点庞杂,所以自己一定要能够静下心来好好的学习。虽然不一定都能涉及到,但是自己一定要精心的学习真正的用脑子思考。

这道题目的意思是:给你N个非递减数列,然后任意给定范围,求得范围内出现最多的次数,并输出。这个题目看似简单,其实想清楚也是比较困难的。

要用到游程编码,这个具体的思想我也不清楚,但是看了题解的思路,我就自己捉摸去了,也不知道自己写的是不是和题解中的思想一致。

具体的思路是这样的,因为RMQ解决的问题是区间内的最大值和最小值的查询问题,那么很显然是要先把区间的出现的次数存起来准备用于RMQ的。然后就是要把每个相同的区域统一编号,每个区域的左边界和右边界也要存起来,这样就可以通过这些区域(块)描述出整个的数组了,有了这样的描述,那么解决问题也就及其的顺手了。

那么,取得的范围[a, b]首先判断a和b对应的是不是一个下标,如果是的话,那么答案直接就能得出,就是b-a+1;不是的话,那么就要分作三段来求了,左边的a到a所在块的右边界,右边的b到b的左边界,和中间的那一块。这样就可以得出答案了。

贴出代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

const int MAXN = 100000 + 11;

vector <int> cnt;

int N, M, A[MAXN];

int d[MAXN][18], L[MAXN], R[MAXN], num[MAXN];

void RMQ_init()
{
	int nc = cnt.size();
//	cout << "nc = " << nc << endl;
	for (int i = 0; i < nc; i++)
	{
		d[i + 1][0] = cnt[i];
//		cout << "cnt[i] = " << cnt[i] << endl;
	}
	for (int j = 1; (1 << j) <= nc; j++)
	{
		for (int i = 1; i + (1 << j) - 1 <= nc; i++)
		{
			d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
		}
	}
}

int RMQ(int l, int r)
{
	if (l > r)
	{
		return 0;
	}
	int k = 0;
	while ((1 << (k + 1)) <= r - l + 1)
	{
		k++;
	}
	return max(d[l][k], d[r - (1 << k) + 1][k]);
}

int main()
{
	while (scanf("%d", &N) != EOF)
	{
		if (N == 0)
		{
			break;
		}
		scanf("%d", &M);
		int start = 1;
		int temp = 1;
		cnt.clear();
		for (int i = 1; i <= N; i++)
		{
			scanf("%d", &A[i]);
		}
		A[N + 1] = 1000000000;
		for (int i = 1; i <= N + 1; i++)
		{
			if (A[i] > A[i - 1])
			{
				cnt.push_back(i - start);
				L[temp] = start;
				R[temp] = i - 1;
				for (int j = start; j < i; j++)
				{
					num[j] = temp;
				}
				start = i;
				temp++;
			}
		}
		int a, b;
		RMQ_init();
		for (int i = 0; i < M; i++)
		{
			scanf("%d%d", &a, &b);
			if (num[a] == num[b])
			{
//				cout << "num_a = " << num[a] << endl;
//				cout << "num_b = " << num[b] << endl;
				printf("%d\n", b - a + 1);
			}
			else
			{
				int ans = 0;
//				cout << "num_a = " << num[a] << endl;
//				cout << "num_b = " << num[b] << endl;
//				cout << "R[a] = " << R[num[a]] << endl;
//				cout << "L[b] = " << L[num[b]] << endl;
				ans = max((R[num[a]] - a + 1), (b - L[num[b]] + 1));
//				cout << "ans1 = " << ans << endl;
				ans = max(ans, RMQ(num[a] + 1, num[b] - 1));
				printf("%d\n", ans);
			};
		
		}
		
	}
//	system("pause");
	return 0;
}

抱歉!评论已关闭.