poj 3368(RMQ)

来源:互联网 发布:夏普网络扫描仪工具 编辑:程序博客网 时间:2024/06/10 00:30

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

这道题目是RMQ(Range Minimum/Maximum Query) 问题变形,寻找在区间内出现的最大频次。
用到动态规划
dp[ i] [j] =max(dp [i ] [j-1] ,dp[i +i<<(j-1) ] [j-1] ;

这道题的关键是如何构建一个dp数组。
我们可以将读取的数组num 变形。
所有相同的元素为 一组,用s[N]表示每组元素的起始下标,e[n]表示每组元素的结束下标,cnt【N】表示每组有多少个相同的元素。用pos[N]数组表示第 i 个元素属于第几个组。

     int id=1; //id表示有多少组     s[1]=id;     for(i=1;i<=n;i++)     {         pos[i]=id;         cnt[id]++;         if(num[i]!=num[i+1]||i==n)         {            e[id]=i;             id++;            s[id]=i+1;          }      } 

完整代码。

#include <iostream>#include <stdio.h>#include <memory.h>using namespace std;const int N=100010;int cnt[N];int pos[N];int e[N];int s[N];int num[N];int dp[N][20];int pow[20];int log2(int n){  int cnt=0;  while(n)  {  cnt++;     n>>=1;   }  return --cnt;}int max(int x,int y){  return x>y?x:y ; }void RMQ(int n){  for(int i=1;i<=n;i++ )  {        dp[i][0]=cnt[i];  }  int temp=log2(n);  for(int j=1;j<=temp;j++)  {    for(int i=1;i+pow[j]-1<=n;i++)       dp[i][j]=max(dp[i][j-1],dp[i+pow[j-1]][j-1]);  }}int getmax(int a,int b){   int k=log2(b-a+1);   return max(dp[a][k],dp[b-pow[k]+1 ][k] );}int main(){  int i,j,n,q;  for(i=1,pow[0]=1;i<20;i++)    pow[i]=2*pow[i-1];  while (cin>>n&&n)  {     memset(cnt,0,sizeof(cnt) );     cin>>q;     for(i=1;i<=n;i++)     {         cin>>num[i];     }     int id=1;     s[1]=id;     for(i=1;i<=n;i++)     {         pos[i]=id;         cnt[id]++;         if(num[i]!=num[i+1]||i==n)         {            e[id]=i;             id++;            s[id]=i+1;          }      }       RMQ(id);      int x,y;      while(q--)      {          scanf("%d%d",&x,&y);          if(pos[x]==pos[y] ) // in the same group          {             cout<<y-x+1<<endl;          }          else           {              int n1=e[pos[x]]-x+1;                 int n2=y-s[pos[y]]+1;              int n3=0;              if( pos[y]-pos[x] >1)  //统计pos[x] 与pos[y] 之间的最大值。              {                   n3=getmax( pos[x]+1,pos[y]-1 );               }              cout<<(  max( max(n1,n2) ,n3) )<<endl;           }     }   }}
0 0