PKU 2828 Buy Tickets 线段树想法题 (第4天)

本文探讨了线段树在解决复杂问题时的高效应用,并通过具体实例展示了其在变形题目中的妙用,从原理到实现,一步步剖析线段树的奥秘。

今天做了两道线段树,还有 昨天的 Bestcoder ,发现线段树真是博大精深,题目的变形也是非常有意思,不想不知道,一想真奇妙。

思路 倒着插,为什么呢?首先最后一个的位置是确定的,倒着放的时候 n-1个是不会对第 n 个产生影响 ,所以放哪就放那了,不会发生变动,那么复杂度就是 O(n)的,怎么用线段树呢?我们思考这样一个问题,对于 i,如果我放第i个,

那么我一定要腾出 i-1个空位 来放 前面的数,所以 线段树的结构 就很明显了 ,用一个变量 记录 这段区间的空余位置

如果剩余的位置 >= i ,也就是放在lson我们 就直接放进去好了,但是如果不够呢,那么我们只能放在rson 的 i-lson的空位出。。。

#include<iostream>
#include<cstdio>
#define lson id << 1
#define rson id << 1|1
using namespace std;
struct line{
    int l,r,len;
    int mid(){
        return (l + r) / 2;
    }
}node[1000008];
int a[200002],b[200002],tmp[200002];
void _Tree(int id ,int l,int r)
{
    node[id].l = l;node[id].r = r,node[id].len = r - l + 1;
    if(l == r) return;
    int mid = node[id].mid();
    _Tree(lson,l,mid);
    _Tree(rson,mid+1,r);
}
void _insert(int id,int k,int n)
{
    node[id].len --;

    if(node[id].l == node[id].r )
    {
        tmp[node[id].l] = b[n];return;
    }

    if(node[lson].len >=k)_insert(lson,k,n);
    else if(node[rson].len >= k-node[lson].len)_insert(rson,k-node[lson].len,n);
}
int main()
{
    int n,m;
    while(~scanf("%d",&n))
    {
        _Tree(1,1,n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);a[i]++;
        }
        for(int i=n;i>=1;i--)
            _insert(1,a[i],i);
        for(int i=1;i<n;i++)
            printf("%d ",tmp[i]);
        printf("%d\n",tmp[n]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值