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\n");//这里,我们说明:因为y>x,所以maxn==0的情况也是不满足题意的。 
52         else printf("%d\n",maxn);
53     }
54 }

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

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

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

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

posted @ 2018-01-15 19:10  JZYshuraK_彧  阅读(297)  评论(0编辑  收藏  举报