POJ 3368 Frequent values

Frequent values
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13382 Accepted: 4928

Description

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.

Input

The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the 
query.

The last test case is followed by a line containing a single 0.

Output

For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.

Sample Input

10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0

Sample Output

1
4
3

Source

解题思路:注意数列是以非递减序给出的,所以区间内保存左起连续相同的数的个数,右起连续相同的数的个数,整个区间的众数的出现的频率,区间合并搞搞就行了(另外如果数列是无序的怎么做?主席树?)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define Max 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct
{
	int lnum;
	int rnum;
	int lsum;
	int rsum;
	int msum;
	bool bottom;
}tree[Max<<2];
void push_up(int rt,int m)
{
	tree[rt].lnum=tree[rt<<1].lnum;
	tree[rt].rnum=tree[rt<<1|1].rnum;
	tree[rt].lsum=tree[rt<<1].lsum;
	tree[rt].rsum=tree[rt<<1|1].rsum;
	if(tree[rt].lsum==m-(m>>1)&&tree[rt<<1].rnum==tree[rt<<1|1].lnum)
		tree[rt].lsum+=tree[rt<<1|1].lsum;
	if(tree[rt].rsum==(m>>1)&&tree[rt<<1].rnum==tree[rt<<1|1].lnum)
		tree[rt].rsum+=tree[rt<<1].rsum;
	if(tree[rt<<1].rnum==tree[rt<<1|1].lnum)
		tree[rt].msum=max(max(tree[rt<<1].msum,tree[rt<<1|1].msum),tree[rt<<1].rsum+tree[rt<<1|1].lsum);
	else
		tree[rt].msum=max(tree[rt<<1].msum,tree[rt<<1|1].msum);
}
void build(int l,int r,int rt)
{
	tree[rt].bottom=false;
	if(l==r)
	{
		scanf("%d",&tree[rt].lnum);
		tree[rt].rnum=tree[rt].lnum;
		tree[rt].lsum=tree[rt].rsum=tree[rt].msum=1;
		tree[rt].bottom=true;
		return ;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	push_up(rt,r-l+1);
}
int query(int L,int R,int l,int r,int rt)
{
	int ans=0;
	if(L<=l&&r<=R)
	{
		ans=tree[rt].msum;
		return ans;
	}
	int m=(l+r)>>1;
	if(L<=m)
		ans=max(ans,query(L,R,lson));
	if(R>m)
		ans=max(ans,query(L,R,rson));
	if(tree[rt<<1].rnum==tree[rt<<1|1].lnum&&R>=m+1&&L<=m&&!tree[rt].bottom)
	{
		int t=min(tree[rt<<1|1].lsum+m,R)-max(L,m-tree[rt<<1].rsum+1)+1;
		ans=max(t,ans);
	}
	return ans;
}
int main()
{
	int m,n,a,b;
	while(~scanf("%d",&n),n)
	{
		scanf("%d",&m);
		build(1,n,1);
		while(m--)
		{
			scanf("%d%d",&a,&b);
			printf("%d\n",query(a,b,1,n,1));
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值