1. 程式人生 > >Sticks Problem POJ

Sticks Problem POJ

單調棧找出每個數a[i]右邊第一個小於等於他的數在哪 記為pos[i] 然後在[i,pos[i]-1]內找一個最靠左的最大值在哪 記為p 則[i,p]即為所求

#include <cstdio>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;

stack <int> stk;
int maxx[200010],id[200010];
int ary[50010],pos[50010];
int n;

void init()
{
    int i;
    while(!stk.empty()) stk.pop();
    for(i=n;i>=1;i--)
    {
        while(!stk.empty()&&ary[i]<ary[stk.top()]) stk.pop();
        if(stk.empty()) pos[i]=n+1;
        else pos[i]=stk.top();
        stk.push(i);
    }
}

void pushup(int cur)
{
    if(maxx[2*cur]>=maxx[2*cur+1])
    {
        maxx[cur]=maxx[2*cur];
        id[cur]=id[2*cur];
    }
    else
    {
        maxx[cur]=maxx[2*cur+1];
        id[cur]=id[2*cur+1];
    }
}

void build(int l,int r,int cur)
{
    int m;
    if(l==r)
    {
        maxx[cur]=ary[l];
        id[cur]=l;
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
}

void query(int pl,int pr,int &res1,int &res2,int l,int r,int cur)
{
    int m;
    if(pl<=l&&r<=pr)
    {
        if(res1<maxx[cur])
        {
            res1=maxx[cur];
            res2=id[cur];
        }
        return;
    }
    m=(l+r)/2;
    if(pl<=m) query(pl,pr,res1,res2,l,m,2*cur);
    if(pr>m) query(pl,pr,res1,res2,m+1,r,2*cur+1);
}

int main()
{
    int i,ans,res1,res2;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++) scanf("%d",&ary[i]);
        init();
        build(1,n,1);
        ans=-1;
        for(i=1;i<=n;i++)
        {
            if(i<pos[i]-1)
            {
                res1=0,res2=0;
                query(i,pos[i]-1,res1,res2,1,n,1);
                ans=max(ans,res2-i);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}