POJ - 3368 Frequent values RMQ或线段树

题目链接:点击查看

题意:n个数,q次询问,区间(l,r) 连续出现的数最多的次数

题解:1、RMQ,保存区间的最大值,但先要把前面和a[l-1]相同的数去掉,对于特殊的数据也是会T的(比如n个数全都相同),这里主要是学习下方法;

2、线段树维护区间最大值,直接就是nlog(n)

RMQ:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+10;
int dp[N][20];
int n,q,a[N];
int main()
{
	while(~scanf("%d",&n)&&n)
	{
		scanf("%d",&q);
		a[0]=-1000000;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			if(i==1||a[i]!=a[i-1]) dp[i][0]=1;
			else dp[i][0]=dp[i-1][0]+1;
		}
		for(int j=1;j<20;j++)
			for(int i=1;i+(1<<j)-1<=n;i++)
				dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
		int l,r,cnt;
		int ans;
		while(q--)
		{
			scanf("%d%d",&l,&r);
			ans=0;
			while(l<=r&&a[l]==a[l-1]) l++,ans++;
			if(l<=r)
			{
				cnt=(int)log2(r-l+1);
				ans=max(ans,max(dp[l][cnt],dp[r-(1<<cnt)+1][cnt]));
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

线段树区间合并,注意判断查询时区间合并

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+10;
struct node{
	int l,r;
	int maxx;
	int ml,mr;
}tree[N<<2];
int n,q,a[N];
void pushup(int cur)
{
	tree[cur].ml=tree[cur<<1].ml;
	if(tree[cur<<1].ml==tree[cur<<1].r-tree[cur<<1].l+1&&a[tree[cur<<1].l]==a[tree[cur<<1|1].l])
		tree[cur].ml=tree[cur<<1].ml+tree[cur<<1|1].ml;
		
	tree[cur].mr=tree[cur<<1|1].mr;
	if(tree[cur<<1|1].mr==tree[cur<<1|1].r-tree[cur<<1|1].l+1&&a[tree[cur<<1|1].r]==a[tree[cur<<1].r])
		tree[cur].mr=tree[cur<<1|1].mr+tree[cur<<1].mr;
	
	tree[cur].maxx=max(tree[cur<<1].maxx,tree[cur<<1|1].maxx);
	if(a[tree[cur<<1].r]==a[tree[cur<<1|1].l])
		tree[cur].maxx=max(tree[cur].maxx,tree[cur<<1].mr+tree[cur<<1|1].ml);
		
}
void build(int l,int r,int cur)
{
	tree[cur].l=l;
	tree[cur].r=r;
	if(l==r)
	{
		tree[cur].maxx=1;
		tree[cur].ml=tree[cur].mr=1;
		return;
	}
	int mid=(r+l)>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
	pushup(cur);
//	cout<<l<<" "<<r<<" "<<tree[cur].maxx<<" "<<tree[cur].ml<<" "<<tree[cur].mr<<endl;;
}
int query(int pl,int pr,int cur)
{
//	cout<<tree[cur<<1|1].l<<" "<<tree[cur].r<<endl;
	if(pl<=tree[cur].l&&tree[cur].r<=pr)
		return tree[cur].maxx;
	int res=0;
	if(pr<=tree[cur<<1].r)
		return query(pl,pr,cur<<1);
	else if(pl>=tree[cur<<1|1].l)
		return query(pl,pr,cur<<1|1);
	else
	{
		res=max(res,query(pl,pr,cur<<1));
		res=max(res,query(pl,pr,cur<<1|1));
		if(a[tree[cur<<1].r]==a[tree[cur<<1|1].l])
			res=max(res,min(pr,tree[cur<<1|1].l+tree[cur<<1|1].ml-1) - max(pl,tree[cur<<1].r-tree[cur<<1].mr+1) + 1);
			return res;
	}
}
int main()
{
	while(~scanf("%d",&n)&&n)
	{
		scanf("%d",&q);
		a[0]=-1000000;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		build(1,n,1);
		int l,r;
		while(q--)
		{
			scanf("%d%d",&l,&r);
			printf("%d\n",query(l,r,1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/88812456