您的位置:首页 > 其它

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

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

这道题目的意思是:给你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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: