POJ 2452 Sticks Problem(ST+二分查找)

Description
给出一长度为n的序列,序列没有重复的数值,问j-i的最大值,其中j,i满足a[i]< a[k]< a[j],i< k< j,如果不存在这样的i,j则输出-1
Input
多组用例,每组用例第一行为一整数n表示序列长度,第二行n个不同的整数表示该序列,以文件尾结束输入
Output
对于每组用例,输出满足条件的j-i的最大值,如果不存在满足条件的i和j则输出-1
Sample Input
4
5 4 3 6
4
6 5 4 3
Sample Output
1
-1
Solution
对于每一个i,从区间[i,n]中找到使得i为区间最小值位置的最大区间[i,t],然后再在区间[i,t]中找到最大值的位置j,用j-i更新答案即可,区间最值可以用ST维护,查找需要二分,最后答案如果为0说明没有满足条件的i,j
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 55555
#define INF 0x3f3f3f3f
int n,a[maxn],sta[maxn],p,smax[maxn][22],smin[maxn][22];
void ST()
{
    for(int i=0;i<n;i++)smax[i][0]=smin[i][0]=i;
    int k=(int)(log(1.0*n)/log(2.0));
    for(int j=1;j<=k;j++)   
        for(int i=0;i+(1<<j)<=n;i++)  
         {
            if(a[smax[i][j-1]]>a[smax[i+(1<<(j-1))][j-1]])smax[i][j]=smax[i][j-1];
            else smax[i][j]=smax[i+(1<<(j-1))][j-1];
            if(a[smin[i][j-1]]<a[smin[i+(1<<(j-1))][j-1]])smin[i][j]=smin[i][j-1];
            else smin[i][j]=smin[i+(1<<(j-1))][j-1];
         }
}
int query_max(int l,int r)  
{  
    int k=(int)(log(1.0*(r-l+1))/log(2.0));  
    if(a[smax[l][k]]<a[smax[r-(1<<k)+1][k]]) return smax[r-(1<<k)+1][k];
    return smax[l][k];
}
int query_min(int l,int r)  
{  
    int k=(int)(log(1.0*(r-l+1))/log(2.0));  
    if(a[smin[l][k]]>a[smin[r-(1<<k)+1][k]]) return smin[r-(1<<k)+1][k];
    return smin[l][k];
}
int binary_search(int x,int l,int r)
{
    while(l<r)
    {
        int mid=(l+r+1)/2;
        if(query_min(x,mid)==x)l=mid;
        else r=mid-1;
    }
    return l;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        ST();
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int j=query_max(i,binary_search(i,i,n-1));
            ans=max(ans,j-i);
        }
        if(ans)printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}

你可能感兴趣的:(POJ 2452 Sticks Problem(ST+二分查找))