zoukankan      html  css  js  c++  java
  • Sticks Problem

    Sticks Problem poj-2452

        题目大意:给你一串n个数的数列a,上面的数为a1到an。我们求最大的y-x,其中,y和x满足1.x<y 2.任意的x<i<y,都有ai>ax&&ai<ay。

        注释:n<=50000,ai<=100000

          想法:我们很容易就想到,松弛x。那么,对于任意的x,y都必须满足这样的条件,就是说y和x之间的所有数,都大于ax。那么,我们就可以处理出任意的x右边的第一个比ax小的数的下标为r[x]。这样,我们就可以显然第知道,y必定存在于x到r[x]之间。那么,什么样的y是最大的且满足题意的呢?不难想到,就是x到r[x]之间的最大值的下标,就是y。这样,我们思考怎样才能实现这个过程?首先,我们需要求出r[x],这是n*n的,我们想优化吧,用单调队列优化,时间复杂度O(nlogn)。然后,我们对于任意的x都有一个唯一的r[x]与之对应,我们想在这段区间内求出这段区间之内的最大值,用ST求RMQ下标即可。

        最后,附上丑陋的代码... ...

     1 #include <iostream>
     2 #include <cstdio>
     3 #define N 50100
     4 using namespace std;
     5 int r[N],f[N][17],a[N],log[N];
     6 int main()
     7 {
     8     int n;
     9     for(int i=2;i<=N;i++) log[i]=log[i>>1]+1;//我们可以直接处理ST中的log数组 
    10     while(~scanf("%d",&n))
    11     {
    12         for(int i=1;i<=n;i++)
    13         {
    14             scanf("%d",&a[i]);
    15         }
    16         for(int i=n+1;i>=1;i--)//单调队列优化,那个(n+1)是极其重要的!! 
    17         {
    18             if(a[i]>a[i+1]) r[i]=i+1;
    19             else
    20             {
    21                 int t=r[i+1];
    22                 while(a[i]<a[t]) t=r[t];    
    23                 r[i]=t;
    24             }
    25         }
    26         r[n+1]=-1;
    27         // for(int i=2;i<=n;i++) log[i]=log[i>>1]+1;
    28         for(int i=1;i<=n+1;i++)//预处理的初始化是下标 
    29         {
    30             f[i][0]=i;
    31         }
    32         for(int i=1;(1<<i)<=n+1;i++)
    33         {
    34             for(int j=1;j+(1<<i)-1<=n+1;j++)
    35             {
    36                 if(a[f[j][i-1]]>a[f[j+(1<<(i-1))][i-1]])//由于我们维护的是下标,所以就比较的麻烦。 
    37                     f[j][i]=f[j][i-1];//其实我开始写的是三目运算符,但是太长了,就写if了。 
    38                 else f[j][i]=f[j+(1<<(i-1))][i-1];
    39             }
    40         }
    41         int maxn=-1;
    42         int len=0;
    43         int maxx;
    44         for(int i=1;i<=n;i++)
    45         {
    46             len=log[r[i]-i+1];
    47             if(a[f[i][len]]>a[f[r[i]-(1<<len)+1][len]]) maxx=f[i][len];
    48             else maxx=f[r[i]-(1<<len)+1][len];//同样,我们在查询时需要注意,我们维护的是下标。 
    49             maxn=max(maxn,maxx-i);
    50         }
    51         if(maxn<=0) printf("-1
    ");//这里,我们说明:因为y>x,所以maxn==0的情况也是不满足题意的。 
    52         else printf("%d
    ",maxn);
    53     }
    54 }

        小结:RMQ是可以维护下标的,只是实现过程有些磨人....

          1.我们需要明确注意,单调队列优化的时候,r[n+1]是坚决不能是0的??!

          2.单调队列处理下标时,不可对a赋值...这种错误只有我会犯了吧。

          3.RMQ中ST的思想的重要性远远大于其代码本身。

  • 相关阅读:
    Android自定义属性,format详解
    设置EditText是否可编辑
    Android中Application设置全局变量以及传值
    android:ellipsize属性的含义
    Java集合框架List,Map,Set等全面介绍
    二十款漂亮的CSS字体样式,让你受用非浅
    IE浏览器不见了
    display属性值:
    用CSS设置多个背景、背景渐变、指定背景大小
    [转]IE6双倍边距——IE布局BUG集锦
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8289444.html