Lost Cows POJ - 2182 线段树 点修改 逆序

题意

有n头牛,每头牛都有一个编号。从排在第二只牛开始,给出这头牛的左边有几只编号比他小的牛。求每一个位置上牛的编号。

题意半天才看懂。。

思路

最后一只牛的编号是可以确定的。如果左边有k头编号比他小的牛,他的编号必为k+1。当最后一头牛的编号确定以后,倒数第二头牛的编号也能确定。所以我们可以倒着访问。

用sum记录所在空间剩余的位置。对于插入在 val 位置的牛他前边一定要有 val -1(1~n 建树)个剩余位置。(0~n 建树则为 val 个剩余位置)

访问结点时,如果左子树的剩余位置大于或等于 val 就访问左子树(sum[rt<<1] >= val ),否则就访问右子树。访问右子树时需要用 val 减去左子树的剩余位置( val -sum[rt<<1] ),即整个线段树的第 val 个空位(空叶子结点),也是在右儿子那的第 val -sum[rt<<1]个空位。

这道题和Buy Tickets POJ - 2828   类似

#include<cstdio>
const int maxn=1e5;
int sum[maxn<<2],p[maxn<<2],ans[maxn];
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void bulid(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    bulid(l,m,rt<<1);
    bulid(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(int val,int pos,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]--;
        ans[pos]=l;
        return ;
    }
    int m=(l+r)>>1;
    if(val<=sum[rt<<1])
        update(val,pos,l,m,rt<<1);
    else
        update(val-sum[rt<<1],pos,m+1,r,rt<<1|1);
    pushup(rt);

}
int main()
{
    int n;
    scanf("%d",&n);
    bulid(1,n,1);
    p[1]=0;
    for(int i=2;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=n;i>0;i--)
        update(p[i]+1,i,1,n,1);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

昨天刚做过一道方法一样的题,今天却想了半天才想到,还是作完题没有认真总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值