标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1806
题目大意:给你一个非降序排列的整数数组,你的任务是对于一系列的询问,(i,j),回答序列中出现次数追的的数的个数;
如下图所示:
AC代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<string> 7 #include<cmath> 8 using namespace std; 9 const int N = 1e5+10; 10 int a[N],b[N]; 11 int dp[N][20]; 12 int n,m; 13 //构造和寻找的代码,来自大白书 14 void buildrmq( ) 15 { 16 for(int i=0;i<n;i++) 17 dp[i][0]=b[i]; 18 for(int j=1;(1<<j)<=n;j++) 19 for(int i=0;i+(1<<j)-1<n;i++) 20 dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); 21 } 22 int search(int s,int v) 23 { 24 int k =0 ; 25 while(1<<(k+1) <= v-s+1) k++; 26 return max(dp[s][k],dp[v-(1<<k)+1][k]); 27 } 28 int bi_search(int s,int t) 29 { 30 int tmp=a[t]; 31 int l=s; 32 int r=t; 33 int mid; 34 while(l<r) 35 { 36 mid=((l+r)>>1); 37 if(a[mid]>=tmp) r=mid; 38 else l=mid+1; 39 } 40 return r; 41 } 42 int main() 43 { 44 int T; 45 while(scanf("%d",&n) && n) 46 { 47 memset(b,0,sizeof(b)); 48 memset(dp,0,sizeof(dp)); 49 scanf("%d",&m); 50 for(int i =0; i<n; i++) 51 scanf("%d",&a[i]); 52 a[n] = a[n-1]+1; 53 for(int i =n-1; i>=0; i--)//倒序统计单个数在当前段出现的次数 54 { 55 if(a[i] == a[i+1]) 56 { 57 b[i] = b[i+1]+1; 58 } 59 else b[i] =1; 60 } 61 buildrmq( );//构造RMQ函数 62 int L,R,ans; 63 for(int i=1; i<=m; i++) 64 { 65 scanf("%d %d",&L,&R); 66 L = L-1;R = R-1;//题目中是从1开始计数的; 67 int temp = bi_search(L,R);//寻找数组中最左端等于a[R]的数 68 ans = b[temp] - b[R]+1; //统计和最左边相同的数出现的次数 69 if(L == temp) printf("%d\n",ans);//如果这一区间中的数字相同的话,直接左边减去右边 70 else printf("%d\n",max(ans,search(L,temp-1)));//否则,寻找(L,temp)中的最大数,进行比较 71 } 72 } 73 return 0; 74 }
poj 1806 Frequent values(RMQ 统计次数) 详细讲解
标签:
原文地址:http://www.cnblogs.com/lovychen/p/4450201.html