zoukankan      html  css  js  c++  java
  • SGU 521 North-East ( 二维LIS 线段树优化 )

    521. "North-East"

    Time limit per test: 0.5 second(s)
    Memory limit: 262144 kilobytes
    input: standard
    output: standard


    The popular music band of international fame "North-East" is coming to Berland! This news has spread all over the country, so numerous fans are now ready to rush and buy all the tickets!

    At present the fans still don't know in which cities the band plans to give concerts. The only thing is known at the moment is that the band will visit several cities, and as their name says, they will strictly move north and east when going to the next city. In other words when the band moves from city i to city j, city j is always located northward and eastward of the city i.

    It's also known that the tour is planned in such a way that the maximum possible number of cities will be visited. The musicians refuse to reveal other details. As you know, fans always get ready for the arrival of their idols, so they would appreciate any single detail about possible movements of their favorite musicians.

    Your task is to help the fans and find two lists of cities — A and B. The first list A should contain the cities, which the band might visit during the tour. The second list B should contain the cities, which the band will have to visit for sure during the tour.

    Input

    The first line of input contains a single integer n (1 ≤ n ≤ 105) — amount of cities in the country. The following n lines contain coordinates of the cities. Each line contains a pair of integersxiyi (-106 ≤ xiyi ≤ 106) — the coordinates of the i-th city. Ox axis is directed west-to-east, and Oy axis — south-to-north. No two given cities will be located at the same point.

    Output

    Print the required list A to the first line of output and B to the second line. Each list should start with the amount of cities in it, followed by the indices of cities in increasing order. Cities are numbered from 1 to n.

    Example(s)
    sample input
    sample output
    5
    3 2
    1 1
    5 5
    2 3
    4 4
    
    5 1 2 3 4 5
    3 2 3 5
    
    sample input
    sample output
    5
    1 1
    10 10
    5 6
    10 1
    6 5
    
    4 1 2 3 5
    2 1 2
    

    题意是可以从某个点出发,走向 x , y 都严格增大的点走 , 问那些点可能在最长路径上 ,那些点必定会经过

    用 dp[0][i] 表示点i 作为右端点的最长路 , dp[1][i] 表示点i 作为左端点的最长路 。

    再判一下 dp[0][i] + dp[1][i]  是否跟最大值相等 , 就可知道它是否第一类点。

    而第二类点直接用一个cnt数组记录一下数字的出现次数是否唯一即可判断 ~

    #include <bits/stdc++.h>
    using namespace std ;
    const int N = 200020 ;
    
    int n ;
    
    struct SegTree {
        #define root 1,n+10,1
        #define lr rt<<1
        #define rr rt<<1|1
        #define lson l,mid,rt<<1
        #define rson mid+1,r,rt<<1|1
        int mx[N<<2]  ;
    
        void Up( int rt ) {
            mx[rt] = max( mx[lr] , mx[rr] ) ;
        }
    
        void Build( int l , int r , int rt ) {
            mx[rt] = 0 ;
            if( l == r ) return ;
            int mid = ( l+r ) >> 1 ;
            Build(lson),Build(rson) ;
        }
    
        void Update( int l , int r , int rt , int x , int v ) {
            if( l == r ) { mx[rt] = v ; return ; }
            int mid = (l+r)>>1;
            if( x <= mid ) Update( lson , x , v );
            else Update( rson , x , v);
            Up(rt);
        }
    
        int Query( int l , int r , int rt , int L , int R ) {
            if( l == L && r == R ) return mx[rt] ;
            int mid = (l+r) >> 1 ;
            if( R <= mid ) return Query( lson , L , R ) ;
            else if( L > mid ) return Query( rson , L , R ) ;
            else return max( Query( lson , L , mid ) , Query( rson , mid + 1 , R ) ) ;
        }
    } T;
    
    struct node {  int x , y , id ; } e[N] ;
    
    inline bool cmp1( const node &a , const node &b ) {
        if( a.x != b.x ) return a.x < b.x ;
        else return a.y < b.y ;
    }
    
    inline bool cmp2( const node &a , const node &b ) {
        if( a.x != b.x ) return a.x > b.x ;
        else return a.y > b.y ;
    }
    
    
    map<int,int>idx;
    vector<int>a;
    int S[N] , top ;
    
    vector<int> ans1 , ans2 ;
    int cnt[N] , dp[2][N] ;
    
    
    void Doit( int k , int p ) {
        for( int i = top - 1 ; i >= 0 ; --i ) {
            int id = idx[ e[p].y ] ;
            dp[k][ e[p].id ] = S[i] ;
            T.Update( root , id , S[i] );
            p-- ;
        }
    }
    
    
    void Gao() {
    
        memset( dp , 0 , sizeof dp ) ;
        memset( cnt , 0 , sizeof cnt ) ;
    
        sort( e + 1 , e + n + 1 , cmp1 ) ;
        T.Build( root ) ; top = 0 ;
        for( int i = 1 ; i <= n ; ++i ) {
            int id = idx[ e[i].y ] ;
            if( i == n || e[i].x != e[i+1].x ) {
                S[top++] = T.Query( root , 1 , id - 1 ) + 1 ;
                Doit( 0 , i );
                top = 0 ;
            } else {
                S[top++] = T.Query( root , 1 , id - 1 ) + 1 ;
            }
        }
        sort( e + 1 , e + n + 1 , cmp2 ) ;
        T.Build( root ) ; top = 0 ;
        for( int i = 1 ; i <= n ; ++i ) {
            int id =  idx[ e[i].y ] ;
            if( i == n || e[i].x != e[i+1].x ) {
                S[top++] = T.Query( root , id + 1 , n + 10 ) + 1 ;
                Doit( 1 , i );
                top = 0 ;
            } else {
                S[top++] = T.Query( root , id + 1 , n + 10 ) + 1 ;
            }
        }
    
    //    for( int i = 1 ; i <= n ; ++i ) cout << e[i].id << ' ' << dp[0][ e[i].id ] << ' ' << dp[1][ e[i].id ] << endl ;
    
        ans1.clear() , ans2.clear() ;
        int len = 0 ;
        for( int i = 1 ; i <= n ; ++i ) len = max( len , dp[0][i] + dp[1][i] ) ;
        for( int i = 1 ; i <= n ; ++i ) if( dp[0][ e[i].id ] + dp[1][ e[i].id ] == len ) ans1.push_back( e[i].id ) , cnt[ dp[0][ e[i].id ] ]++ ;
        for( int i = 1 ; i <= n ; ++i ) if( dp[0][ e[i].id ] + dp[1][ e[i].id ] == len && cnt[ dp[0][e[i].id] ] == 1 ) ans2.push_back( e[i].id ) ;
    }
    
    void Output() {
        sort( ans1.begin() , ans1.end() ) , sort( ans2.begin() , ans2.end() ) ;
        printf("%d",ans1.size()); for( int i = 0 ; i < ans1.size() ; ++i ) printf(" %d",ans1[i]);puts("");
        printf("%d",ans2.size()); for( int i = 0 ; i < ans2.size() ; ++i ) printf(" %d",ans2[i]);puts("");
    }
    
    int main() {
        while( ~scanf("%d",&n) ) {
            idx.clear(); a.clear(); 
            for( int i = 1 ; i <= n ; ++i ) {
                scanf("%d%d",&e[i].x,&e[i].y);
                e[i].id = i ;
                a.push_back( e[i].y );
            }
            sort( a.begin() , a.end() ) ;
            int tot = 2 ;
            for( int i = 0 ; i < a.size() ; ++i ) {
                if( idx.find( a[i] ) == idx.end() ) {
                    idx[ a[i] ] = tot++ ;
                }
            }
            Gao(); Output();
        }
        return 0 ;    
    }
    View Code
  • 相关阅读:
    ExtJS的定时任务(转)
    Web开发系列–GIS(转)
    Windows Mobile 6.0模拟器的浏览器中不能访问本机网址
    JS定时保存表单数据(UserData 行为)
    查询Sqlserver数据库死锁的一个存储过程(转)
    ExtJS4.0在IE9中出现了SCRIPT5007: 无法获取属性“flex”的值
    Microsoft Device Emulator 模拟器菜单 中文
    错误:网站辅助进程已被 IIS 终止(Debug 时是不是弹出)
    集成验证时IE采用Kerberos 还是NTLM验证方式?(摘抄)
    SQLServer 2005死锁终极大法(自动杀) 转
  • 原文地址:https://www.cnblogs.com/hlmark/p/4521496.html
Copyright © 2011-2022 走看看