poj 3368(RMQ裸题)
传送门:https://vjudge.net/problem/POJ-3368
题意:给你一个不降序列,q次询问,问你l到r区间出现最多次的次数。
最近因为一些闲事都没怎么打题,状态不是特别好。
这题就是水题啦。我们可以知道,l到r的出现次数最多,这个数可以是左连续,或者右连续,又或者在中间。由于题目给的是不降序列,所以左右连续的情况可以用一个upper_bound、lower_bound解决。至于中间情况,就用rmq求最大值就好。a数组存原来数据,b数组存出现多少次。比如 a:-1,-1,1,1,1,1,3,5,5,。则b数组对应为0,2,0,0,0,4,1,0,2,。就是只统计这一段出现的次数,然后就裸题了。
上代码。
1 // Cease to struggle and you cease to live 2 #include <iostream> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <stack> 12 using namespace std; 13 typedef long long ll; 14 const int N=1e5+7; 15 int a[N],b[N],rmq[N][20]; 16 int pw(int k){ 17 int res=1; 18 while(k--) res*=2; 19 return res; 20 } 21 int getk(int l,int r){ 22 int k=0; 23 while(r-l+1>=pw(k+1)) ++k; 24 return k; 25 } 26 int main() { 27 int n,qn; 28 while(~scanf("%d",&n) && n){ 29 scanf("%d",&qn); 30 for(int i=1;i<=n;++i) scanf("%d",&a[i]); 31 for(int i=1;i<=n;){ 32 int p=upper_bound(a+1,a+1+n,a[i])-a-1; 33 for(int j=i;j<p;++j) b[j]=0; 34 b[p]=p-i+1; 35 i=p+1; 36 } 37 for(int i=1;i<=n;++i) rmq[i][0]=b[i]; 38 for(int u=1;u<=20;++u){ 39 for(int i=1;i+pw(u)<=n;++i){ 40 rmq[i][u]=max(rmq[i][u-1],rmq[i+pw(u-1)][u-1]); 41 } 42 } 43 for(int i=1;i<=qn;++i){ 44 int l,r;scanf("%d%d",&l,&r); 45 int p1=upper_bound(a+1,a+1+n,a[l])-a; 46 --p1; 47 if(p1>r) p1=r; 48 int p2=lower_bound(a+1,a+1+n,a[r])-a; 49 if(p2<l) p2=l; 50 int res=max(p1-l+1,r-p2+1); 51 if(p1+1<=p2-1){ 52 int k=getk(p1+1,p2-1); 53 res=max(res,max(rmq[p1+1][k],rmq[p2+1-pw(k)][k])); 54 } 55 printf("%d\n",res); 56 } 57 } 58 return 0; 59 }