zoukankan      html  css  js  c++  java
  • POJ 2452 Sticks Problem (线段树+递归)

    题意:给一个正整数序列,记为a1,a2,……an,现需找i,j,使得i<j,并且ai与aj之间的数均比ai大,均比aj小,求符合上述条件的i与j,使得j-i的最大。

    分析:易知序列中的最小值比其他所有数都小,最大值比其他所有数都大,所以可以现找到最小的数与最大的数的位置,记为i,j,若i<j,则区间[i,j]内符合上述条件的最值就是j-i,然后递归求解左右区间[1,i-1],[j+1,n],若i>j,则将区间分为三段递归求解,[1,j],[j+1,i-1],[i,n]。递归边界为区间左端点>=区间右端点时返回-1。每次求区间的最大与最小值的位置可以用线段树解决。

    View Code
    #include <stdio.h>
    #define N 50010
    int n;
    int a[N];
    int max[4*N],min[4*N];
    int MIN(int i,int j)
    {
        return a[i]<a[j]?i:j;
    }
    int MAX(int i,int j)
    {
        return a[j]>a[i]?j:i;
    }
    void update(int cur)
    {
        int ls=cur<<1,rs=cur<<1|1;
        min[cur]=MIN(min[ls],min[rs]);
        max[cur]=MAX(max[ls],max[rs]);
    }
    void build(int cur,int x,int y)
    {
        int mid=x+y>>1,ls=cur<<1,rs=cur<<1|1;
        if(x==y)
        {
            min[cur]=max[cur]=x;
            return;
        }
        min[cur]=n+1;
        max[cur]=0;
        build(ls,x,mid);
        build(rs,mid+1,y);
        update(cur);
    }
    int query_min(int cur,int x,int y,int s,int t)
    {
        int mid=x+y>>1,ls=cur<<1,rs=cur<<1|1;
        if(x==s && y==t)    return min[cur];
        if(mid<s)   return query_min(rs,mid+1,y,s,t);
        if(mid+1>t) return query_min(ls,x,mid,s,t);
    
        int l=query_min(ls,x,mid,s,mid);
        int r=query_min(rs,mid+1,y,mid+1,t);
        return MIN(l,r);
    }
    int query_max(int cur,int x,int y,int s,int t)
    {
        int mid=x+y>>1,ls=cur<<1,rs=cur<<1|1;
        if(x==s && y==t)    return max[cur];
        if(mid<s)   return query_max(rs,mid+1,y,s,t);
        if(mid+1>t) return query_max(ls,x,mid,s,t);
    
        int l=query_max(ls,x,mid,s,mid);
        int r=query_max(rs,mid+1,y,mid+1,t);
        return MAX(l,r);
    }
    int solve(int x,int y)
    {
        if(x<1 || y>n || x>=y)    return -1;
        int id_min=query_min(1,1,n,x,y);
        int id_max=query_max(1,1,n,x,y);
        if(id_max>id_min)
        {
            int i=solve(x,id_min-1);
            int j=id_max-id_min;
            int k=solve(id_max+1,y);
            k=k>=i?k:i;
            k=k>=j?k:j;
            return k;
        }
    
        int i=solve(x,id_max);
        int j=solve(id_max+1,id_min-1);
        int k=solve(id_min,y);
        k=k>=i?k:i;
        k=k>=j?k:j;
        return k;
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)   scanf("%d",&a[i]);
            a[0]=-1;
            a[n+1]=100001;
            build(1,1,n);
            printf("%d\n",solve(1,n));
        }
        return 0;
    }
  • 相关阅读:
    集合
    二维数组
    数组案例
    数组
    date time 和string
    if和for的案例
    if条件语句 for循环语句
    Windows Azure Mangement API 之 更方便的使用Mangement API
    Azure Table storage 之改进DynamicTableEntity类为其添加动态语言扩展
    Windows Azure Table storage 之 动态Table类 DynamicTableEntity
  • 原文地址:https://www.cnblogs.com/algorithms/p/2622431.html
Copyright © 2011-2022 走看看