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

来源:互联网 发布:淘宝售后率怎么算 编辑:程序博客网 时间:2024/06/06 04:22

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 0x3f3f3f3fint 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;}
0 0
原创粉丝点击