Uva_11235_Frequent values

T^T做这题就是各种泪~卡了将近2小时,各种Judging error、越界与WA。

题解:整个数组是非降序的,所有相等元素都会聚集在一起。开一个num数组,用num[i]来记录第i段相等的元素有多少个(也就是说相当于RMQ中的元素值了),num数组的长度就是原数列不同元素的个数(段数),l数组记录i段元素的上界,r数组记录i段元素的下界,用一个mark数组记录i位置的元素属于第几段。假设询问区间为a,b:

L=mark[a],R=mark[b];

ans=max(r[L]-a+1,b-l[R]+1,夹在这两个段中最大值)

图解:

Uva_11235_Frequent values

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cmath>

#include<string>

using namespace std;

#define N 100005

int mark[N],val,num[N],l[N],r[N],maxsum[N][25],re; //mark记录i位置的元素是第几段

void RMQ()

{

    for(int i=1;i<=re;++i)

    maxsum[i][0]=num[i];

    for(int j=1;(1<<j)<=re+1;++j)

        for(int i=1;i+(1<<j)-1<=re;++i)

            maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);

}

int Max(int a,int b,int c)

{

    if(a<b) a=b;

    if(a<c) a=c;

    return a;

}

int main(){

  int n,q,i,j,k,L,R;

  while(~scanf("%d",&n)&&n)

  {

      re=1; //re记录的是第几段

      scanf("%d%d",&q,&k);

      val=k;

      num[1]=1;

      mark[1]=1;

      l[0]=1;

      for(i=2;i<=n;++i)

      {

          scanf("%d",&k);

          if(k==val) 

          {

              num[re]++;

              mark[i]=re;

          }

          else

          {

              r[re]=i-1;

              re++;

              mark[i]=re;

              l[re]=i;

              val=k;

              num[re]=1;

          }

      }

      RMQ();

      while(q--)

      {

          scanf("%d%d",&L,&R);

          if(mark[L]==mark[R])

              printf("%d\n",R-L+1);

          else

          {

              int ans=0;

              if(mark[L]+1<=mark[R]-1) //如果两段中存在段

              {

              int k=(int)((log(mark[R]-mark[L]-1))/log(2.0));

               ans=max(maxsum[mark[L]+1][k],maxsum[mark[R]-(1<<k)][k]);

              }

               ans=Max(r[mark[L]]-L+1,ans,R-l[mark[R]]+1);

               printf("%d\n",ans);

          }

      }

  }

  return 0;

}

 

你可能感兴趣的:(value)