Buy Tickets POJ - 2828线段树求插队

题意就是给你n个人,每个人有自己的要插入的pos和val,问你最后的排序

思路:逆序插入,最后一个人的位置一定是固定的,因为必须连续插入,所以第i个人插入的时候必须保证前面有pos[i]个空位,

那么用线段树记录位置个数,如果位置不够,就往后挪。

#include<iostream>
#include<cstdio>
using namespace std;

#define N 200005

int spare[N<<2];
int seq[N];
int pos[N],val[N];

void pushdown(int rt)
{
        spare[rt]=spare[rt*2]+spare[rt*2+1];
}
void build(int rt,int l,int r)
{
        if(l==r)
        {
                spare[rt]=1;
                return;
        }
        int mid=(l+r)/2;
        build(rt*2,l,mid);
        build(rt*2+1,mid+1,r);
        pushdown(rt);
}
void insert(int pos,int val,int rt,int l,int r)
{
        if(l==r)
        {
                seq[l]=val;
                spare[rt]=0;
                return;
        }
        int mid=(l+r)/2;
        if(pos<spare[rt*2])
        {
                insert(pos,val,rt*2,l,mid);
        }
        else
        {
                insert(pos-spare[rt*2],val,rt*2+1,mid+1,r);
        }
        pushdown(rt);
}
int main()
{

    int n;
    while(~scanf("%d",&n))
    {
        build(1,1,n);
        for (int i=0; i<n ; i++ )
        {
                scanf("%d %d",&pos[i],&val[i]);
        }
        for (int i=n-1;i>=0 ;i-- )
        {
                insert(pos[i],val[i],1,1,n);
        }
        for (int i=1;i<=n ;i++ )
        {
                if(i==n)
                {
                        printf("%d\n",seq[i]);
                }
                else
                printf("%d ",seq[i]);
        }
    }
    return 0;

}

原文地址:https://www.cnblogs.com/Json-Five/p/9821732.html

时间: 2024-08-03 20:29:26

Buy Tickets POJ - 2828线段树求插队的相关文章

Buy Tickets POJ - 2828 思维+线段树

Buy Tickets POJ - 2828 思维+线段树 题意 是说有n个人买票,但是呢这n个人都会去插队,问最后的队列是什么情况.插队的输入是两个数,第一个是前面有多少人,第二个是这个人的编号,最后输出编号就好了. 解题思路 这个题要倒着处理,因为最后一个人插队完成后,别人就不能影响他了.他前面有n个人,那么他就是n+1号位置上,这样来的话,我们只需要知道那个位置,他前面有n个人就行.默认每个位置都没有人. 详细看代码. 代码实现 #include<cstdio> #include<

poj 2828 线段树

http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 并且后来的也可以确定----如果从前往后,所有的随时都不是确定的 2.线段树叶子节点直接维护区间(线段)信息,非叶子节点v维护的是以v为树根的整个子树的信息,那么假设父节点rt信息为[l,r]那么左子树维护[l,mid],右子树维护[mid+1,r]的信息.如果如果是前缀和,rt里是1-n的和,左子树1~n/2的和,右子树是n/2+1~n

poj 2828 Buy Tickets 万能的线段树大法。

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 14400   Accepted: 7199 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue- The Lunar New Year wa

POJ 2828 (线段树 单点更新) Buy Tickets

倒着插,倒着插,这道题是倒着插! 想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0. 从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的个数. 说一下那个坑爹的第56行的判断: if(i > 1) printf(" "); 将输出的n个数用空格隔开,我感觉这是一个还算常用的写法啊,结果各种莫名TLE,加上输入挂也补救不回来. 去掉这个无谓的判断后,3594MS险过,加上输入挂3094MS,还算是起到了一定的加速作用.

poj 2828(线段树 逆向思考) 插队是不好的行为

http://poj.org/problem?id=2828 插队问题,n个人,下面n行每行a,b表示这个人插在第a个人的后面和这个人的编号为b,最后输出队伍的情况 涉及到节点的问题可以用到线段树,这里因为每个人插队时有顺序的,如果按照正着的顺序来情况太复杂,所以可以试试倒过来,从最后一个人开始,此时找到的位置 一定是最终位置,这样就很简单了,   结构体中多开一个mark表示每个区间的空位置,多开一个sum表示人的编号 这道题不错,提醒我们有时候换一换思路,逆向思考一下 1 #include<

【POJ】Buy Tickets(思路 + 线段树)

一开始没有思路,之后问了一下学长,需要逆向处理输入. 最后一个加入队列的肯定是没有冲突的,所以我们可以从最后一个开始处理,从后往前,找第 i + 1个空着的地方. 线段树的话记录 区间中 空白位置的个数. 13441833 201301052100 2828 Accepted 5368K 1704MS C++ 1690B 2014-09-14 21:19:45 #include<iostream> #include<cstdlib> #include<cstdio> #

poj 2828(线段树单点更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 18561   Accepted: 9209 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue… The Lunar New Year wa

POJ 2828 线段树(想法)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15422   Accepted: 7684 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue… The Lunar New Year wa

POJ 2828 线段树应用

这道题是之前一场比赛碰到的题目,当时看到题时以为是一道用链表优化的水题,交了几遍一直超时,简直不能再感人(┬_┬)今天有空突然想起去查了下题解,是用线段树做的.....完全想不到啊有木有~思路大概就是每个节点存当前节点下还剩多少空位,然后倒序查找该人所需要的位置,具体细节看代码吧. Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15801   Accepted: 7876 Description