码迷,mamicode.com
首页 > 编程语言 > 详细

uvalive 6609(RMQ算法)

时间:2016-05-09 18:48:32      阅读:290      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4621

题目大意:

求给定长度为n的数列里子序列和大于等于x的最短子序列的长度。

 

本以为是动态规划,看了题解才知道有固定算法就能解(RMQ,其实也是变相的dp)

RMQ问题是求给定区间中的最值问题。理论上每次实践效率为O(n),据说线段树法可以将算法优化到O(logn)(在线段树中保存线段的最值)。

传说中还有一种名为Sparse_Table的算法,它可以在O(nlogn)的预处理以后实现O(1)的查询效率(然而我实在看不懂QAQ).

poj 2823 为同类型经典,可练手。

  1. #include <iostream>  
  2. #include <cstring>  
  3. #include <cstdlib>  
  4. #include <cstdio>  
  5. #include <queue>  
  6. #include <vector>  
  7. #include <algorithm>  
  8. #include <cmath>  
  9. #include <map>  
  10. #include <set>  
  11. #include <stack>  
  12. #include <string.h>  
  13. using namespace std;  
  14.   
  15. #define eps 1e-8  
  16. const double pi=acos(-1.0);  
  17. typedef long long LL;  
  18. const int Max=500100;  
  19. const int INF=1000000007;  
  20. int n,x;  
  21. LL dp[Max][30];  
  22. int mm[Max];  
  23. //初始化RMQ, b数组下标从1开始,从0开始简单修改  
  24. void RMQ(int n,LL b[])  
  25. {  
  26.     mm[0] = -1;  
  27.     for(int i = 1; i <= n; i++)  
  28.     {  
  29.         mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];  
  30.         dp[i][0] = b[i];  
  31.     }  
  32.     for(int j = 1; j <= mm[n]; j++)  
  33.         for(int i = 1; i + (1<<j) -1 <= n; i++)  
  34.             dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);  
  35. }  
  36. //查询最大值  
  37. LL query(int x,int y)  
  38. {  
  39.     int k = mm[y-x+1];  
  40.     return max(dp[x][k],dp[y-(1<<k)+1][k]);  
  41. }  
  42. LL num[Max];  
  43. LL sum[Max];  
  44. int main()  
  45. {  
  46.     int t;  
  47.     cin>>t;  
  48.     while(t--)  
  49.     {  
  50.         scanf("%d%d",&n,&x);  
  51.         for(int i=1; i<=n; i++)  
  52.             scanf("%lld",num+i),sum[i]=sum[i-1]+num[i];  
  53.         RMQ(n,sum);  
  54.         int ans=n+3;  
  55.         for(int i=0; i<n; i++)  
  56.         {  
  57.             int l=i+1,r=n;  
  58.             while(l<r)  
  59.             {  
  60.                 int mid=(l+r)/2;  
  61.                 if(query(i+1,mid)-sum[i]>=x)  
  62.                     r=mid;  
  63.                 else  
  64.                     l=mid+1;  
  65.             }  
  66.             if(sum[r]-sum[i]>=x)  
  67.                 ans=min(ans,r-i);  
  68.             if(sum[l]-sum[i]>=x)  
  69.                 ans=min(ans,l-i);  
  70.         }  
  71.         if(ans==n+3)  
  72.             ans=-1;  
  73.         cout<<ans<<endl;  
  74.     }  
  75.     return 0;  

uvalive 6609(RMQ算法)

标签:

原文地址:http://www.cnblogs.com/zznulw/p/5474920.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!