POJ 2823 阉割版线段树

此题的较好方法为单调队列。稍后实现一下。用阉割的线段树来写9600ms++囧~

简单的线段树就不说了,详情可以看以前的文章或者下面的代码.....

虽然有点凑数量之嫌....


#include<iostream>
#define MAXN 1000001
using namespace std;

int _max[MAXN<<2];
int _min[MAXN<<2];

int mx( int a,int b ){
    return a>b?a:b;
}
int mn( int a,int b ){
    return a<b?a:b;
}

void PushUp( int rt )
{
     _max[rt]=mx( _max[rt<<1],_max[rt<<1|1] );
     _min[rt]=mn( _min[rt<<1],_min[rt<<1|1] );
}

void build(int l,int r,int rt)
{
     if( l==r ){
         scanf( "%d",&_max[rt] );
         _min[rt]=_max[rt];
         return ;
     }
     int m=(l+r)>>1;
     build( l,m,rt<<1 );
     build( m+1,r,rt<<1|1 );
     PushUp(rt);
}

int query( int l,int r,int c,int L,int R,int rt )
{
    if( l<=L&&R<=r )
    {
        if( c )
        return _max[rt];
        else
        return _min[rt];
    }
    int m=(L+R)>>1;
    int res;
    if( c )
    { 
        res=-214748363;
        if( l<=m ) res=mx(res,query( l,r,c,L,m,rt<<1) );
        if( m<r ) res=mx( res,query( l,r,c,m+1,R,rt<<1|1) );
        return res;
    }
    else
    {
        res=214748363;
        //res=100;
        if( l<=m ) res=mn(res,query( l,r,c,L,m,rt<<1) );
        if( m<r ) res=mn( res,query( l,r,c,m+1,R,rt<<1|1) );
        return res;
    }
}

int main()
{
    int n,c,i;
    while( scanf( "%d %d",&n,&c)!=EOF )
    {
           build(1,n,1);
           printf( "%d",query( 1,c,0,1,n,1 ) );
           for( i=2;;i++ )
           {
                if( i+c-1<=n ){
                    printf( " %d",query( i,i+c-1,0,1,n,1 ) );
                }
                else
                    break;
           }
           printf( "\n%d",query( 1,c,1,1,n,1 ) );
           for( i=2;;i++ )
           {
                if( i+c-1<=n ){
                    printf( " %d",query( i,i+c-1,1,1,n,1 ) );
                }
                else
                    break;
           }
           printf( "\n" );
    }
    return 0;
}


你可能感兴趣的:(POJ 2823 阉割版线段树)