The last test case is followed by a line containing a single 0.
題目大意: 給定一個不遞減長度爲n的序列,給定m個詢問,每次詢問[li,ri]內上鏡率最高的那個數的出現次數。
由於題中說明輸入數據是一個非遞減數列,可以知道相等的數字都集中在一起,然後可以將它們按出現的次數存入另一個數組運用RMQ求出區間出現的最大值,這時候要處理好左邊界,由於數字如果相等則數組是從左往右遞增的我們要處理好左邊界。
例子:
輸入的數組 :1 2 3 4 4 4 4 4 4 3 3 3
轉化後數組: 1 1 1 1 2 3 4 5 6 1 2 3
這個時候查詢9-11這個區間 轉化後的數組爲 6 1 2,如果直接找最大值就是6,而正確答案是2.
所以要先從左邊界開始找到一個不大於1的值並用sum記錄下來,之後再用RMQ求最值與sum比較求得答案。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
const int N=100099;
int dp[N][30],a[N],num[N];
void RMQ(int n)
{
for(int i=1; i<=n; i++)
{
dp[i][0]=a[i];
}
for(int j=1; (1<<j)<=n; 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 main()
{
int n,q;
while(scanf("%d",&n)&&n)
{
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
scanf("%d",&q);
for(int i=1; i<=n; i++)
scanf("%d",&num[i]);
//記錄出現次數
for(int i=1; i<=n; i++)
{
if(i==1)
{
a[i]=1;
continue;
}
if(num[i]==num[i-1])
a[i]=a[i-1]+1;
else
a[i]=1;
}
RMQ(n);
while(q--)
{
int x,y,sum=0;
scanf("%d%d",&x,&y);
while(a[x]>1&&x<=y) //處理左側邊界 記錄sum的值
{
if(a[x]>1)
{
sum++;
x++;
}
else break;
}
if(x>=y&&sum==0) printf("1\n");//如果數組中出現 1 1這樣的值
else if(x>=y&&sum!=0) printf("%d\n",sum);//如果出現數組中7 1這樣的值
else
{
int k=log10(y-x+1)/log10(2);
int mi=max(dp[x][k],dp[y-(1<<k)+1][k]);
mi=max(mi,sum);
printf("%d\n",mi);
}
}
}
return 0;