Buy Tickets(poj 2828)

题意:排队买票,但是 中途 出现插队情况,比如 0 123,代表值为123的人 插入到 0 的位置,如果后面 出现 0 456,那么新的 0的位置就是 456,123就变成是 1的位置了

分析:这道题应该从后往前插入,当要插的位置小于左边的空位数时,就往左边插,否则往右边插,并且此刻插的位置要减去左边的空位数

#include<cstdio>
#include<iostream>
#define lson l,m,now*2
#define rson m+1,r,now*2+1
#define M 200010
using namespace std;
int sum[M*4],ans[M];
struct node
{
    int pos,zh;
};node per[M];
void push_up(int now)
{
    sum[now]=sum[now*2]+sum[now*2+1];
}
void build(int l,int r,int now)
{
    if(l==r)
    {
        sum[now]=1;
        return;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    push_up(now);
}
void change(int p,int v,int l,int r,int now)
{
    if(l==r)
    {
        ans[l]=v;
        sum[now]=0;
        return;
    }
    int m=(l+r)/2;
    if(p<sum[now*2]) change(p,v,lson);
    else change(p-sum[now*2],v,rson);
    push_up(now);
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        build(0,n-1,1);
        for(int i=0;i<n;i++)
          scanf("%d%d",&per[i].pos,&per[i].zh);
        for(int i=n-1;i>=0;i--)
          change(per[i].pos,per[i].zh,0,n-1,1);
        for(int i=0;i<n;i++)
          printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}

时间: 2024-10-09 15:21:04

Buy Tickets(poj 2828)的相关文章

Buy Tickets POJ - 2828 思维+线段树

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

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]

Buy Tickets+POJ+线段树单点更新的灵活运用

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 12927   Accepted: 6410 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 【线段树点更新】

题目:poj 2828 Buy Tickets 题意:有n个人排队,每个人有一个价值和要插的位置,然后当要插的位置上有人时所有的人向后移动一位当这个插入到这儿,如果没有直接插进去. 分析:分析发现直接插入移动的话花时间太多,我们可不可以用逆向思维.从后往前来,因为最后一个位置是肯定能确定的,而其他的则插入空的第某个位置. 比如第一组样例: 4 0 77 1 51 1 33 2 69 开始时候位置都为空 编号0 1 2 3 首先从最后一个来2 69 第二个位置空,则可以直接放 然后编号变为0 1

poj 2828 Buy Tickets

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 13277   Accepted: 6595 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 (线段树)

题目大意: 排队有人插队,每一次都插到第 i 个人的后面. 最后输出顺序. 思路分析: 你会发现,如果反向处理的话,你就知道这个人是第几个了. 那么问题一下子就简化了. 就是在线段树上找第几个空位置就行了. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define lson num<<1

POJ 2828 Buy Tickets 线段树解法

此题应用线段树的方法非常巧妙.没做过真的难想得出是这么想的. 是一个逆向思维的运用. 其实一看到这道题目我就想到要运用逆向思维的了,但是就是没那么容易想通的. 思路: 1 要从后面往前更新线段树 2 线段树记录的是当前区间还剩下多少个记录空间 3 因为后面的插入会使得前面的插入往后退,那么前面插入的下标如果大于前面可以插入的空间,就需要往后退了. 好难理解的操作.仔细观察一下下面update这个函数吧. 二分地去查找适合的插入位置,把插入操作时间效率提高到 O(lgn),如果使用一般方法插入操作

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

题目传送门 1 /* 2 结点存储下面有几个空位 3 每次从根结点往下找找到该插入的位置, 4 同时更新每个节点的值 5 */ 6 #include <cstdio> 7 #define lson l, m, rt << 1 8 #define rson m+1, r, rt << 1 | 1 9 10 const int MAX_N = 200000 + 10; 11 int pos[MAX_N], val[MAX_N]; 12 int sum[MAX_N <&

POJ 2828 poj 2828 Buy Tickets 【树状数组,已知前n项和为K,返回n值】

题目链接:http://poj.org/problem?id=2828 在一个队列中,一个人想要插队,告诉你每个新来的人会插在i个人后面,求出最后的队列. 如果我们用模拟的话,那么时间复杂度肯定是超了:想想,如果我们逆序,那么最后来的人的位置一定是固定的,这样的话,我们将问题转化成逆序扫描给出数据,插在i个人后面这个数据就变成了在这个人前面需要留出多少个空位.如此我们只需要用树状数组记录前n项总共有多少个空位,每扫描一个数据,就找出能使得他前面正好有i个空位. 这题用树状数组或者线段树都可以,今