Poj-2182

两种解法:

1.直接数组

2.线段树降低时间复杂度

#include <bits/stdc++.h>
using namespace std;

int n;
int pre[10000];
int ans[10000];

// 构建区间为1-n的线段树
struct node {
    int l, r;
    int len; // 当前节点有多少牛
    node() {}
    node(int l, int r, int value) : l(l), r(r), len(value) {}
} tree[40000];

// 初始化1-n的线段树
void build_tree(int l, int r, int u) {
    if (l > r) return;
    tree[u].l = l;
    tree[u].r = r;
    tree[u].len = r - l + 1;
    if (l == r) return; // 到达叶子节点,退出递归
    int mid = (l + r) >> 1;
    build_tree(l, mid, u << 1);
    build_tree(mid + 1, r, (u << 1) + 1);
}

// 查询第 num 小的元素 u 是当前结点
int query(int u, int num) {
    tree[u].len--;
    if (tree[u].l == tree[u].r) return tree[u].l; // 到达叶子节点
    if (tree[u << 1].len < num) {
        return query((u << 1) + 1, num - tree[u << 1].len);
    } else {
        return query(u << 1, num);
    }
}

int main() {
    cin >> n;
    pre[1] = 0;
    for (int i = 2; i <= n; i++) {
        cin >> pre[i];
    }
    build_tree(1, n, 1);
    for (int i = n; i >= 1; i--) {
        ans[i] = query(1, pre[i] + 1);
    }
    for (int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值