您的位置:首页 > 产品设计 > UI/UE

UVa 11235 / POJ 3368 Frequent values (想法题&RMQ线段树维护最长区间长度)

2014-02-19 12:24 501 查看
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=501&page=show_problem&problem=2176

http://poj.org/problem?id=3368

思路:

由于序列是非降的,把相同元素视作一个区间,然后统计出每个区间的左端点left和右端点right,再用线段树维护区间长度的最大值

记待查询区间[a,b]的a对应的区间为intera,b对应的区间为interb,则当interb==intera时,最大频率为b-a+1;当interb>intera时,最大频率为max(max(right[intera] - a + 1, b - left[interb] + 1), query(intera + 1, interb - 1, root)))

完整代码:

/*UVa: 0.225s*/
/*POJ: 1250ms,1648KB*/

#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define root 0, cnt, 1
const int mx = 100005;

int maxs[mx << 2], left[mx], right[mx], interval[mx], ii;

inline void pushup(int rt)
{
	maxs[rt] = max(maxs[rt << 1], maxs[rt << 1 | 1]);
}

void build(int l, int r, int rt)
{
	if (l == r)
	{
		maxs[rt] = right[ii] - left[ii] + 1;
		++ii;
		return;
	}
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
	pushup(rt);
}

int query(int ql, int qr, int l, int r, int rt)
{
	if (ql <= l && r <= qr)
	{
		return maxs[rt];
	}
	int maxs = 0, m = (l + r) >> 1;
	if (ql <= m) maxs = query(ql, qr, lson);
	if (m < qr) maxs = max(maxs, query(ql, qr, rson));
	return maxs;
}

int main()
{
	int n, q, val, cnt, i, x, a, b, intera, interb;
	while (scanf("%d%d", &n, &q), n)
	{
		val = -mx, cnt = -1;
		for (i = 1; i <= n; ++i)
		{
			scanf("%d", &x);
			if (x != val) val = x, ++cnt, left[cnt] = right[cnt] = i;
			else ++right[cnt];
			interval[i] = cnt;
		}
		ii = 0;
		build(root);
		while (q--)
		{
			scanf("%d%d", &a, &b);
			intera = interval[a], interb = interval[b];
			if (interb == intera) printf("%d\n", b - a + 1);
			else if (interb == intera + 1) printf("%d\n", max(right[intera] - a + 1, b - left[interb] + 1));
			else printf("%d\n", max(max(right[intera] - a + 1, b - left[interb] + 1), query(intera + 1, interb - 1, root)));
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: