关闭

Frequent values

标签: 线段树
113人阅读 评论(0) 收藏 举报
分类:
链接:http://poj.org/problem?id=3368

题目:You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.

题意:给一串数字(升序),求任意区间内出现次数最多的数字出现的次数。

分析:靠这道题终于第一次临摹了线段树,虽然没有用到lazy算法。这个线段树的手法不是很标准,因为按照升序排列,所以线段是拍好的,不需要维护修改,所以叶子结点直接存储每个线段的长度,其他节点保存其子孙里最长的线段长度。这样在计算任意区间的时候最多比较三次,左侧的不完全线段,右侧的不完整线段,以及中间完整线段中的最长线段长度(这个用线段树的性质容易得到)。在计算的时候要维护一个前缀和来计算区间端点所在的叶节点位置,以及用来计算左右不完整线段的长度。

题解:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <functional>
#include <cmath>
#include <cctype>
#include <cfloat>
#include <climits>
#include <complex>
#include <deque>
#include <list>
#include <set>
#include <utility>
#define rt return
#define fr freopen("in.txt","r",stdin)
#define fw freopen("out.txt","w",stdout)
#define ll long long
#define ull unsigned long long
#define detie ios_base::sync_with_stdio(false);cin.tie(false);cout.tie(false)
#define pii pair<int,int>
#define lowbit(x) x&(-x)
using namespace std;
#define maxi 0x3f3f3f3f
#define MAX 100010

int v[MAX], sum[MAX];
int n, q, cnt;

struct tree
{
	int l, r, m;
	tree() {};
	tree(int a, int b, int c) {
		l = a, r = b, m = c;
	}
}a[4 * MAX];

void build(int l, int r, int root) 
{
	a[root].l = l;
	a[root].r = r;
	if (l == r)
		a[root].m = v[l];
	else {
		int mid = (l + r) / 2;
		build(l, mid, 2 * root);
		build(mid + 1, r, 2 * root + 1);
		a[root].m = max(a[2 * root].m, a[2 * root + 1].m);
	}
}

int querry(int l, int r, int root)
{
	if (l <= a[root].l&&a[root].r <= r){
		rt a[root].m;
	}
	else {
		int mid = (a[root].l + a[root].r) / 2;
		if (r <= mid)rt querry(l, r, 2 * root);
		else if (l > mid)rt querry(l, r, 2 * root + 1);
		else rt max(querry(l, mid, 2 * root), querry(mid + 1, r, 2 * root + 1));
	}
}

int binary_search(int k)
{
	int l = 1, r = cnt;
	while (l < r)
	{
		int mid = (l + r) / 2;
		if (sum[mid] >= k){
			r = mid;
		}
		else {
			l = mid + 1;
		}
	}
	return l;
}

int main()
{
	//fr;
	detie;
	while (~scanf("%d", &n) && n)
	{
		memset(a, 0, sizeof a);
		memset(v, 0, sizeof v);
		memset(sum, 0, sizeof sum);
		cnt = 0;
		scanf("%d", &q);
		int pre, num;
		pre = maxi;
		for (int i = 0; i < n; i++)
		{
			scanf("%d", &num);
			if (num == pre)
				v[cnt]++;
			else {
				v[++cnt]++;
				pre = num;
			}
		}
		for (int i = 1; i <= cnt; i++)
		{
			sum[i] = sum[i - 1] + v[i];
		}
		build(1, cnt, 1);
		while (q--)
		{
			int i, j, ans;
			scanf("%d %d", &i, &j);
			int L = binary_search(i);
			int R = binary_search(j);
			if (L == R)
				printf("%d\n", j - i + 1);
			else {
				ans = max(sum[L] - i + 1, j - sum[R - 1]);
				if (L <= R - 2) {
					ans = max(ans, querry(L + 1, R - 1, 1));
				}
				printf("%d\n", ans);
			}
		}
	}
	rt 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3751次
    • 积分:597
    • 等级:
    • 排名:千里之外
    • 原创:59篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    友情链接