poj2452——Sticks Problem

题目大意:给出n个数,找出Si为最小值Sj为最大值的子序列Si...Sj,求出所有这样的子序列中j-i的最大值

输入:(可以有很多case)

            n (n <= 50000)

            n个数(空格分隔) (not larger than 100000)

输出:如果有这样的子序列就输出j-i,如果没有就输出-1

分析:RMQ问题。枚举区间的起始位置,二分搜索出第一个比起始位置数小的位置r,RMQ求出这个区间内最大值的位置k,如果这个最大值大于起始位置的值,就更新答案,然后循环判断完所有起始位置即可。

代码:转载自http://blog.csdn.net/hexianhao/article/details/51028370

  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<cmath>  
  5. using namespace std;  
  6.   
  7. const int maxn = 50005;  
  8. int n,stick[maxn],dp_max[maxn][20],dp_min[maxn][20];  
  9.   
  10. int _max(int l,int r)  
  11. {  
  12.     if(stick[l] > stick[r]) return l;  
  13.     return r;  
  14. }  
  15.   
  16. int _min(int l,int r)  
  17. {  
  18.     if(stick[l] < stick[r]) return l;  
  19.     return r;  
  20. }  
  21.   
  22. void initRMQ()  
  23. {  
  24.     for(int i = 1; i <= n; i++)  
  25.         dp_max[i][0] = dp_min[i][0] = i;  
  26.     for(int j = 1; (1 << j) <= n; j++)  
  27.         for(int i = 1; i + (1 << j) - 1 <= n; i++)  
  28.         {  
  29.             dp_max[i][j] = _max(dp_max[i][j-1],dp_max[i+(1<<j-1)][j-1]);  
  30.             dp_min[i][j] = _min(dp_min[i][j-1],dp_min[i+(1<<j-1)][j-1]);  
  31.         }  
  32. }  
  33.   
  34. int MaxValue(int l,int r)  
  35. {  
  36.     int k = (int)(log(double(r) - l + 1) / log(2.0));    
  37.     return _max(dp_max[l][k],dp_max[r-(1<<k)+1][k]);  
  38. }  
  39.   
  40. int MinValue(int l,int r)  
  41. {  
  42.     int k = (int)(log(double(r) - l + 1) / log(2.0));    
  43.     return _min(dp_min[l][k],dp_min[r-(1<<k)+1][k]);  
  44. }  
  45.   
  46. int binsearch(int x,int l,int r)  
  47. {  
  48.     while(l < r)  
  49.     {  
  50.         int mid = (l + r) >> 1;  
  51.         if(stick[x] < stick[MinValue(l,mid)])  
  52.             l = mid + 1;  
  53.         else r = mid;  
  54.     }  
  55.     return l;  
  56. }  
  57.   
  58. int main()  
  59. {  
  60.     while(scanf("%d",&n)!=EOF)  
  61.     {  
  62.         for(int i = 1; i <= n; i++)  
  63.             scanf("%d",&stick[i]);  
  64.         initRMQ();  
  65.         int ans = 0;  
  66.         for(int i = 1; i + ans < n; i++){  
  67.             int r = binsearch(i,i+1,n);  
  68.             int k = MaxValue(i,r);  
  69.             if(stick[k] > stick[i])  
  70.                 ans = max(ans,k - i);  
  71.         }  
  72.         if(ans == 0) printf("-1\n");  
  73.         else printf("%d\n",ans);  
  74.     }  
  75.     return 0;  
  76. }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值