zoukankan      html  css  js  c++  java
  • POJ2182 Lost Cows

    POJ2182 Lost Cows

    博客图片

    题目概述

    POJ2182 Lost Cows

    题目概述

    给出一个从(1-N)这个(N)个数字的前面比它大的数字的个数,输出原始的输入序列.输入首先是(N),然后是(N-1)个整数,表示从第二个数开始,它前面有多少个数字比它大.输入数据规模:

    [1leq N leq 8cdot10^3 ]

    题目分析

    从最后一个元素开始,既然前面比它大的数字有(a[n])个,那么它是(1sim N)中第(pre[n]+1)大的数字,然后用同样的方法可以求出倒数第二个,倒数第三个,(ldots).这里面注意之前已经调出的数字在后面的排序中不应该出现,可以用一个数组标记这个数此前有没有使用,可以在(O(n))的时间确定一个整数,整个程序的时间复杂度为(O(n^2)).

    利用树状数组的特性,可以在(O(log(n)))时间内找到剩下的数中的第(pre_i +1)大的数字.树状数组的特性是一个节点可以控制前面几个节点,比如(lowbit(4)=4),表明前面的(tree[1],tree[2],tree[3],tree[4])的改变都可以影响(tree[4]).设定(tree[i]=lowbit(i)),表示数(i)前面的有多少个是改变会影响(tree[i])的值,在初始时而且(sum(i))恰好表示的是(i)是第几个数.当某一个数(k)被取出来后,通过修改(tree[k])的值,确切来说是将(tree[k])减一,然后后面只要被(tree[k])影响的结点的值都会发生改变.

    以题目中给出的样例来说,记过初始化后tree:

    1 2 3 4 5
    1 2 1 4 1

    从后向前,查询第一个数,得到的是1,然后把tree[1]减一,然后与tree[1]相关的都会减一,得到

    1 2 3 4 5
    0 1 1 3 1

    然后是计算sum(x)2x得到的是3,然后add(3,-1)得到:

    1 2 3 4 5
    0 1 0 2 1

    然后是就散sum(x)3时的x得到x4,然后add(4,-1)得到:

    1 2 3 4 5
    0 1 0 1 1

    然后是就散sum(x)2时的x得到x5,然后add(5,-1)得到:

    1 2 3 4 5
    0 1 0 1 0

    最后是就是那sum(x)1时的x得到2,再计算add(2,-1)得到:

    1 2 3 4 5
    0 0 0 0 0

    占坑:一定是糊涂了,没法表述清楚,后面有时间一定更新重写.

    代码

    /*
     * @Author: Shuo Yang
     * @Date: 2020-08-05 11:41:18
     * @LastEditors: Shuo Yang
     * @LastEditTime: 2020-08-05 12:34:42
     * @FilePath: /Code/2182.cpp
     */
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5;
    int pre[N];
    int tree[N];
    int n;
    
    inline int lowbit(int x){
        return x & -x;
    }
    
    void add(int x, int v){
        while(x <= n){
            tree[x] += v;
            x += lowbit(x);
        }
    }
    
    int sum(int x){
        int ans = 0;
        while( x > 0){
            ans += tree[x];
            x -= lowbit(x);
        }
        return ans;
    }
    
    
    int binary_find(int v){
        int l = 1;
        int r = n;
        while(l < r){
            int mid = (l + r)/2;
            if( sum(mid) < v){
                l = mid + 1;
            }else{
                r = mid;
            }
        }
        // printf("l=%d
    ",l);
        return l;
    }
    
    int buf[N];
    
    int main(int argc, const char** argv) {
        scanf("%d", &n);
        tree[1] = lowbit(1);
        for(int i = 2; i <= n; ++i){
            scanf("%d",&pre[i]);
            tree[i] = lowbit(i);
        }
        for(int i = n; i > 0;--i){
            int x = binary_find(pre[i]+1);
            // printf("i=%d,x=%d",i,x);
            add(x, -1);
            buf[i] = x;
        }
        for(int i = 1; i <= n; ++i ){
            printf("%d
    ",buf[i]);
        }
        return 0;
    }
    

    其它

  • 相关阅读:
    zoj 3593 One Person Game
    poj 2115 C Looooops
    hdu 1576 A/B
    hdu 2669 Romantic
    poj1006 Biorhythms
    中国剩余定理(孙子定理)
    Pseudoprime numbers---费马小定理
    青蛙的约会----POJ1061
    [POJ2942]:Knights of the Round Table(塔尖+二分图染色法)
    [BZOJ1718]:[Usaco2006 Jan] Redundant Paths 分离的路径(塔尖)
  • 原文地址:https://www.cnblogs.com/2018slgys/p/13441585.html
Copyright © 2011-2022 走看看