Advanced Guide to Algorithm Competition---0x42 (Tree Array) Lost Cows

Topic

Insert picture description here

answer

  1. Let’s look at the sample in the question first. For the given data, we can push from the back to the front. At the beginning, the cow’s height set {1, 2, 3, 4, 5} (each height can only be used once). The given data of 5 cows is 0, which means that there is no cow in front of it, and its height is 1. The remaining set {2,3,4,5}, for the fourth cow, the given data is 1. It means that there is only 1 cow shorter than it in the remaining set, which is the second smallest, indicating that its height is 3, and so on, we can calculate the height of each cow, so we can find that,For each cow ai, we only need to find a number ranked ai+1 in the remaining set, which is the height of the cow
  1. Then our current problem is transformed into two problems: find the k-th smallest number from the remaining numbers and delete a certain number, so that we can use many methods, such as balanced trees, but it is more troublesome, we still use Do it with a tree array. To continue the transformation, we use the array subscript to represent each height, initialized to 1, which means that each height can only be used once, so deleting a certain number will become add(x, -1). For operation 1, we can use dichotomy
  1. Because our sum seeks the prefix sum, then it must be an increasing sequence,Finding the k-th smallest number from the remaining numbers is equivalent to finding a smallest x in two, so that sum(x)=k (because the sequence is initialized with 1, the deletion becomes 0, so the value of the prefix sum Is the current ranking)

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1e5 + 10;
int n;
int h[N];
int tr[N];
int res[N];

int lowbit(int x) {
    
    
    return x & -x;
}

void add(int x, int c) {
    
    
    for (int i = x; i <= n; i += lowbit(i)) {
    
    
        tr[i] += c;
    }
}

int sum(int x) {
    
    
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) {
    
    
        res += tr[i];
    }
    return res;
}

int main() {
    
    

    cin >> n;
    for (int i = 2; i <= n; i++) scanf("%d", &h[i]);

    //初始化每个区间都为1(优化:每个区间的值其实就是长度)
    for (int i = 1; i <= n; i++) tr[i] = lowbit(i);

    for (int i = n; i >= 1; i--) {
    
    
        int k = h[i] + 1;
        int l = 1, r = n;
        while (l < r) {
    
    
            int mid = (l + r) >> 1;
            if (sum(mid) >= k) r = mid;
            else l = mid + 1;
        }
        res[i] = l;
        add(l, -1);
    }
    for (int i = 1; i <= n; i++) cout << res[i] << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/113836784