POJ 3368/RMQ/线段数

时间:2023-03-09 08:16:40
POJ 3368/RMQ/线段数

题目链接[http://poj.org/problem?id=3368]

给出一段序列,询问[L,R]区间内最大相同数的个数。
用一个很巧妙地方法,转化成求区间内的最大值的问题。
RMQ维护区间最大值。
MAX处理:
*/

for(int i = ; i < n; i++)
{
if(a[i] == a[i - ])
d[i] = d[i - ] + ;
else
d[i] = ;
}

/*
给出一个序列,1、1、1、1、2、3、4、5.
长度为8,求[2,8];即{1、1、1、2、3、4、5},暴力求出3,(前三个数相同),然后RMQ[5,8],取两者最大值。说一来麻烦,举个栗子。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn =+;
int a[maxn];
int d[maxn];
int dp[maxn][];
int n,q;
int l,r;
int RMQ(int l,int r)
{
int k=log((double)(r-l+))/log(2.0);//学长的写法,可以的。
return max(dp[l][k],dp[r-(<<k)+][k]);
}
int main ()
{
while(scanf("%d",&n),n)
{
scanf("%d",&q);
for(int i=;i<n;i++)
scanf("%d",&a[i]);
d[]=;
for(int i=;i<n;i++)
{
if(a[i]==a[i-])
d[i]=d[i-]+;
else
d[i]=;
}
for(int i=;i<n;i++)
dp[i][]=d[i];
for(int k=;(<<k)<=n;k++)
for(int i=;i+(<<k)-<n;i++)
dp[i][k]=max(dp[i][k-],dp[i+(<<(k-))][k-]);
for(int i=;i<q;i++)
{
scanf("%d%d",&l,&r);
l--;
r--;
if(l>r)
continue;
if(l==r)
printf("1\n");
else
{
int t=l;
while(t<r&&a[t]==a[t+])t++;
int ans=t-l+;
if(t==r||t+==r)
printf("%d\n",ans);
else
{
printf("%d\n",max(ans,RMQ(t+,r)));
}
}
}
}
return ;
}