poj2182 Lost Cows--线段树,树状数组(点修改)

Lost Cows

题目描述

N(2<=N<=8000)头奶牛在1…N范围内拥有不同的排名。到了排队吃晚饭的时候,他们没有按照排名的升序排队。

遗憾的是,FJ没有办法对它们进行排序。此外,他不太善于观察问题。他没有写下每头牛的排名,而是确定了一个相当愚蠢的统计数字:对于每一头牛,他知道排在那头牛前面的牛的数量,这些牛的排名比那头牛小。

根据这些数据,告诉FJ奶牛的确切顺序。

输入

第1行:单个整数N

第2…N行:这些N-1行描述了排在给定奶牛前面且排名小于该奶牛的奶牛数量。当然,没有一头牛排在第一头牛之前,所以她没有被列入名单。输入的第2行描述了前面的奶牛数量,其排名小于槽2中的奶牛;第3行描述了之前的奶牛数量,其品牌小于槽3中的奶牛;

输出

第1…N行:N行输出中的每一行都表示一头牛的排名。输出的第#1行表示第一头牛的排名;第2行显示第二头牛的排名;

样例输出

5
1
2
1
0

样例输入

2
4
5
3
1

线段树cpp

//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
template <typename T> void debug(string s, T x) { cout << s << "=" << x << "\n"; }
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
const ll N = 1e4 + 5;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
struct {
    ll l, r, len;      //  用len存储这个区间的数字个数,即这个结点下牛的数量。
}tree[4 * N];           //这里开4倍大,因为线段树的空间需要。
ll pre[N], ans[N];
void BuildTree(ll left, ll right, ll u) {     // 建树。
    tree[u].l = left;
    tree[u].r = right;
    tree[u].len = right - left + 1;              //更新结点u的值
    if (left == right)return;
    BuildTree(left, (left + right) >> 1, u << 1);    //递归左子树。
    BuildTree(((left + right) >> 1) + 1, right, (u << 1) + 1);    //递归右子树。
}
ll query(ll u, ll num) {    //查询+维护。所求值为当前区间的左起第num个元素。
    tree[u].len--;         //对访问到的区间维护len。即把这个结点上牛的数量减去一。
    if (tree[u].l == tree[u].r)return tree[u].l;
    //情况1:左子区间内牛的个数不够,则查询右子区间的左起第num - tree[u<<1].len个元素。
    if (tree[u << 1].len < num)return query((u << 1) + 1, num - tree[u << 1].len);
    //情况2:左子区间内牛的个数足够,则依旧查询左子区间的左起第num个元素。
    if (tree[u << 1].len >= num)return query(u << 1, num);
}
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    
    ll n;
    cin >> n;
    for (ll i = 2; i <= n; i++)cin >> pre[i];
    BuildTree(1, n, 1);
    for (ll i = n; i >= 1; i--)ans[i] = query(1, pre[i] + 1);//  从后往前推断出每次最后一个数字。
    for (ll i = 1; i <= n; i++)cout<<ans[i]<<"\n";

    return 0;
}

数组数组cpp

#include<bits/stdc++.h>
using namespace std;
template <typename T> void debug(string s, T x) { cout << s << "=" << x << "\n"; }
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
const ll N = 1e4 + 5;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;

const ll maxv = N;//区间最大值
ll Binary_Indexed_Tree[N];//树状数组
ll lowbit(ll x) {//数状数组lowbit()
    return x & -x;
}
void update(ll index, ll val) {//在index位置加上val
    while (index <= maxv) {
        Binary_Indexed_Tree[index] += val;
        index += lowbit(index);
    }
}
ll sum(ll index) {//求Binary_Indexed_Tree[1 , index]的和
    ll ans = 0;
    while (index) {
        ans += Binary_Indexed_Tree[index];
        index -= lowbit(index);
    }
    return ans;
}

ll pre[N];
ll vis[N];
ll n;
ll solve(ll pos) {
    ll k=0;
    for (ll i = 1; i <= n; i++) {
        if (!vis[i]) {
            k++;
            if (k == pos) {
                vis[i] = 1;
                return i;//返回第pos大的且未重复选过的数
            }
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);

    cin >> n;
    for (ll i = 2; i <= n; i++)cin >> pre[i];
    for (ll i = n; i >= 1; i--)update(i, solve(pre[i] + 1));//ans[i] = query(1, pre[i] + 1);//  从后往前推断出每次最后一个数字。
    for (ll i = 1; i <= n; i++)cout<< sum(i)-sum(i-1)<<"\n";

    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值