zoukankan      html  css  js  c++  java
  • SPOJ 227 Ordering the Soldiers 线段树 / 树状数组

    题意:设原数组为a[i],pos[i]代表第 i 个位置之前有多少个数比a[i]大,求原数组a[i]。

    这个题意是看了别人的题解才明白,我自己没读出来……

    方法:假设我们从左往右放,因为后面的数还有可能影响前面的数的位置,所以在最后一个数放完之前,我们没法确定每个数的位置,所以我们反过来考虑,从右往左放。因为每个数前面比它大的数的个数pos[i]已知,我们可以不必关心这些数的具体数值,从而转化为它从右往左走了多少个空格,即pos[i]个,因此这个数放在第 pos[i] + 1 个空格位置上。这个空格所在位置的下标id,即是a[i]。a[i] = id;

    树状数组或线段树记录区间[1, i ]的空格个数,对于放好的数,相应区间的空格数减1。

    树状数组代码:5360 ms

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    
    const int MAXN = 200010;
    
    int pos[MAXN];
    int C[MAXN];
    int ans[MAXN];
    bool vis[MAXN];
    int N;
    
    int lowbit( int x )
    {
        return x&(-x);
    }
    
    void Add( int x, int val )
    {
        while ( x <= N )
        {
            C[x] += val;
            x += lowbit(x);
        }
        return;
    }
    
    int Query( int x )
    {
        int res = 0;
        while ( x > 0 )
        {
            res += C[x];
            x -= lowbit(x);
        }
        return res;
    }
    
    //注意二分查找的写法,不然很容易死循环
    void BiSearch( int l, int r, int val, int &addr )
    {
        int mid;
        while ( l <= r )
        {
            mid = ( l + r ) >> 1;
            int sum = Query( N ) - Query( mid - 1 );
            //printf( "mid=%d sum=%d
    ", mid, sum );
            if ( sum > val ) l = mid + 1;
            else
            {
                if ( sum == val )
                {
                    if ( !vis[mid] ) //需要特殊判断一下这个点之前是否已经放好了
                    {
                        addr = mid;
                        r = mid - 1;
                    }
                    else
                    {
                        l = mid + 1;
                    }
                }
                else r = mid - 1;
            }
        }
        return;
    }
    
    int main()
    {
        int T;
        scanf( "%d", &T );
        while ( T-- )
        {
            scanf( "%d", &N );
            memset( C, 0, sizeof(int)*( N + 1 ) );
            memset( vis, false, sizeof(bool)*( N + 1 ) );
            for ( int i = 1; i <= N; ++i )
            {
                scanf( "%d", &pos[i] );
                Add( i, 1 );
            }
    
            for ( int i = N; i > 0; --i )
            {
                int id;
                BiSearch( 1, N, pos[i] + 1, id );
                ans[i] = id;
                vis[id] = true;
                //printf( "id = %d
    ", id );
                Add( id, -1 );
            }
            printf( "%d", ans[1] );
            for ( int i = 2; i <= N; ++i )
                printf( " %d", ans[i] );
            puts("");
        }
        return 0;
    }
    View Code

    线段树代码:1840 ms

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    
    const int MAXN = 200010;
    
    int pos[MAXN];
    int sum[MAXN << 2];
    int ans[MAXN];
    int N, id;
    
    void build( int l, int r, int rt )
    {
        sum[rt] = r - l + 1;
        if ( l == r ) return;
    
        int m = ( l + r ) >> 1;
        build( lson );
        build( rson );
        return;
    }
    
    void Update( int po, int l, int r, int rt )
    {
        --sum[rt];
        if ( l == r )
        {
            id = l;
            return;
        }
    
        int m = ( l + r ) >> 1;
    
        if ( po <= sum[rt << 1] ) Update( po, lson );
        else Update( po - sum[rt << 1], rson );
    
        return;
    }
    
    int main()
    {
        int T;
        scanf( "%d", &T );
        while ( T-- )
        {
            scanf( "%d", &N );
            build( 1, N, 1 );
            for ( int i = 1; i <= N; ++i )
                scanf( "%d", &pos[i] );
    
            for ( int i = N; i > 0; --i )
            {
                Update( pos[i] + 1, 1, N, 1 );
                ans[i] = N - id + 1;
            }
            printf( "%d", ans[1] );
            for ( int i = 2; i <= N; ++i )
                printf( " %d", ans[i] );
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3223343.html
Copyright © 2011-2022 走看看