Line segment tree-Difficult Lost Cows

 

Total time limit: 2000ms

Single test point time limit: 1000ms

Memory limit: 65536kB

description

N (2 <= N <= 100,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands.

Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.

Given this data, tell FJ the exact ordering of the cows.

enter

* Line 1: A single integer, N

* Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on.

Output

* Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.

Sample input

5
1
2
1
0

Sample output

2
4
5
3
1

【analysis】

Calculate the data first, try to summarize the algorithm, and find that it should be considered backwards

For each position, we need to find the number iso [0,i-1]that the unused number is exactly a[i](input array)

One way of thinking is to use an array, cnt[i] represents the number of unused numbers [0, i-1], and then binary search. The query time complexity is only O(log N), but the update time complexity is O(N).

Another way of thinking is the line segment tree, the interval [l, r] stores the number of unused numbers. The query operation here is not the interval query we have learned, but the idea of ​​interval decomposition is still used, which is very interesting.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 100005;

struct node {
    int cnt;
};

node tree[MAXN*4];
int a[MAXN];
int ans[MAXN];

void build_tree(int root, int l, int r)
{
    tree[root].cnt = r - l + 1;

    if (l == r)
        return ;
    
    int mid = (r + l) / 2;
    build_tree(root*2+1, l, mid);
    build_tree(root*2+2, mid+1, r);
}

/* 
 * 1. return the brand i, such that in brand [l, i] there is num unused 
 * 2. set brand i to be used
 */
int find(int root, int l, int r, int num)
{
    // printf("calling find(root=%d, l=%d, r=%d, num=%d)\n", root, l, r, num);
    // printf("cnt = %d\n", tree[root].cnt);
    
    if (l == r) {
        --tree[root].cnt;
        return l;
    }
    
    int mid = (l+r)/2;
    int rt;
    if (tree[root*2+1].cnt >= num)
        rt = find(root*2+1, l, mid, num);
    else
        rt = find(root*2+2, mid+1, r, num-tree[root*2+1].cnt);
    --tree[root].cnt;
    return rt;
}

int main()
{
    int N;
    scanf("%d", &N);
    build_tree(0, 0, N-1);
    for (int i = 1; i < N; ++i)
        scanf("%d", &a[i]);
    for (int i = N-1; i >= 0; --i) {
        ans[i] = find(0, 0, N-1, a[i]+1) + 1;
    }
    for (int i = 0; i < N; ++i)
        printf("%d\n", ans[i]);
    system("pause");
    return 0;
}

It should be noted that since a root subscript only corresponds to the unique interval [l, r] (it has nothing to do with N, it has nothing to do with the title), so the data structure node can also not store l, r, in the parameters of the recursive function In the embodiment can be.

Guess you like

Origin blog.csdn.net/w112348/article/details/109036190