1. 程式人生 > >【POJ2182】Lost Cows

【POJ2182】Lost Cows

【POJ2182】Lost Cows

題面

vjudge

題解

從後往前做
每掃到一個點\(i\)以及比前面小的有\(a[i]\)個數
就是查詢當前的第\(a[i]+1\)
然後查詢完將這個數刪掉
兩個操作可以用平衡樹實現
但是我比較懶用了\(01trie\)
據說暴力也可以過
程式碼

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> 
using namespace std;

inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
    if (ch == '-') w = -1 , ch = getchar();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return w * data;
}
const int MAX_N = 80005;
struct Trie { int ch[2], size; } t[MAX_N * 18]; int tot; 
void insert(int v) { 
    int o = 1; t[o].size++; 
    for (int i = 17; i >= 0; i--) { 
        int c = v >> i & 1; 
        if (!t[o].ch[c]) t[o].ch[c] = ++tot; 
        t[o = t[o].ch[c]].size++; 
    } 
} 
void erase(int v) {
    int o = 1; t[o].size--; 
    for (int i = 17; i >= 0; i--) { 
        int c = v >> i & 1; 
        t[o = t[o].ch[c]].size--; 
    } 
} 
int Kth(int k) {
    int o = 1, res = 0; 
    for (int i = 17; i >= 0; i--) {
        int sz = t[t[o].ch[0]].size; 
        if (k <= sz) o = t[o].ch[0]; 
        else k -= sz, res |= 1 << i, o = t[o].ch[1]; 
    } 
    return res; 
}
int N, a[MAX_N], ans[MAX_N]; 
int main () {
    N = gi(); for (int i = 1; i < N; i++) a[i + 1] = gi(); ++tot; 
    for (int i = 1; i <= N; i++) insert(i); 
    for (int i = N; i >= 1; i--) { 
        ans[i] = Kth(a[i] + 1); 
        erase(ans[i]);
    }
    for (int i = 1; i <= N; i++) printf("%d\n", ans[i]); 
    return 0; 
}