Uva 11235 Frequent Values

因为整个数组是非降序的,所以相同的数字一定是连续的

对于每次询问(X,Y) 可分为(X, R[X]),(R[X]+1,L[Y]-1),(L[Y],Y)三部分求解

其中易得(X,R[X]) = R[X]-X+1, (L[Y],Y)= Y-L[Y]+1;

 可用conut【i】记录每个元素A[i]出现的次数,因为(R[X]+1,L[Y]-1)中的每个元素的所有部分都在该区间内,所以(R[X]+1,L[Y]-1)=max{count【i】|  R[X]+1<=i <= L[Y]-1}

 不过之间的位运算有个地方没注意,然后RE了。。。

代码:

 

#include <stdio.h>
#include <string.h>
#define maxn 100000

int a[maxn+5];
int R[maxn+5]; //下标为i的右端点
int L[maxn+5];// 左端点
int count[maxn+5]; //i的右端点减去左端点
int  dp[maxn+5][20]; //以i为起点,2^j长度的count的最大值 


int max(int a, int b)
{
	return a> b? a: b;
}
 
int main()
{
	int n, q;
	while(scanf("%d",&n)!=EOF && n)
	{
		scanf("%d",&q);
		for(int i= 1; i<= n; i++)
			scanf("%d",&a[i]);
		L[1]= 1;
		R[1]= 1;
		for(int i= 2; i<= n; i++)
			if(a[i]== a[i-1])
			{
				L[i]= L[i-1];
				R[i]= R[i-1]+1;
			}
			else
			{
				L[i]= R[i]= i;
			}	
		for(int i= n-1; i>= 1; i--)
			if(L[i]== L[i+1])
				R[i]= R[i+1];
		for(int i= 1; i<= n; i++)
			count[i]= R[i]- L[i]+ 1;
		for(int i= 1; i<= n; i++)
			dp[i][0]= count[i];
		for(int j= 1; (1<<j) <= n; j++)
			for(int i= 1; (i-1)+(1<<j)<= n; i++)
				dp[i][j]= max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
				//dp[i][j]= max(dp[i][j-1], dp[i+1<<(j-1)][j-1]); 我之前是这样写的,然后就RE了。 
		while(q--)
		{
			int x, y;
			scanf("%d %d",&x,&y);
			if(L[x] == L[y])
				printf("%d\n",y-x+1);
			else if(R[x]+1==L[y])
				printf("%d\n",max(R[x]-x+1,y-L[y]+1));
			else 
			{
				int ans;
				int k= 0;
				int l= R[x]+ 1;
				int r= L[y]- 1;
				while((1<<k+1) <= r-l+1)
					k++;
				ans= max(dp[l][k], dp[r-(1<<k)+1][k]);
				ans= max(ans, R[x]- x+ 1);
				ans= max(ans, y- L[y]+ 1);
				printf("%d\n",ans);
			}		
		}							
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值