poj 2828 Buy Tickets (排队问题+线段树)

/*

//不想写题解了,就直接把人家的粘过来了

线段树节点中保存这一段中的空位数,然后倒序对pos插入:

    例如:  

0 77

1 51

1 33

2 69

  先取: 2 69  ——  ——  —69—   ——   (需要前面有3个空位才能插入)

然后取: 1 33   ——   —33—    —69—    ——   (需要前面有2个空位才能插入)

然后取: 1 51   ——   —33—    —69—    —51—   (需要前面有2个空位才能插入)  前面只有1个空位  故插入后面空格

  然后取: 0 77   —77—   —33—    —69—    —51—   (需要前面有1个空位才能插入)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[maxn<<2],a,b;
struct qw{
    int a,val,num;
}an[maxn];
int cmp(struct qw x,struct qw y){
    return x.num<y.num;
}
void push_up(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt){
    if(l==r){
        sum[rt]=1; return;
    }
    int m=(l+r)>>1;
    build(lson); build(rson);
    push_up(rt);
}
void update(int p,int l,int r,int rt){
    if(l==r){
        sum[rt]=0; return;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,lson);
    else update(p,rson);
    push_up(rt);
}
int q;
//二分查找q,使得sum(1,q)==p; i就是此点要插入的位置
void bina_query(int p,int l,int r,int rt){
    if(l==r&&p==sum[rt]){     //刚开始少了(l==r)这个条件,因为必须是确定到某点之后恰好为p,所以不加会错
        q=r; return;
    }
    int m=(l+r)>>1;
    if(p<=sum[rt<<1]) bina_query(p,lson);
    else bina_query(p-sum[rt<<1],rson);
}
int main(){
    int i,j,n;
    while(~scanf("%d",&n)){
        build(1,n,1);
        for(i=1;i<=n;i++) scanf("%d%d",&an[i].a,&an[i].val);
        //倒着插入
        for(i=n;i>=1;i--){
            bina_query(an[i].a+1,1,n,1);
            an[i].num=q;
            update(q,1,n,1);
        }
        sort(an+1,an+1+n,cmp);
        for(i=1;i<n;i++) printf("%d ",an[i].val);
        printf("%d\n",an[i].val);
    }
    return 0;
}

由于某个人想要插入posi位置,插入后他就在posi位置上了,但是可能其他人会插到他前面来,他的位置就会变成[在他后面且插在他位置及以前的人数]+posi

如果这样就开始求了,当然用线段树就可以做了,就跟求逆序数对一样。

但是我们可以反着来考虑,只要从后面开始站,假设后面的人都已经站在正确的位置上了,那么到那个人站的时候,现在的位置上已经都是后面的那些人了,

只要数posi个空格,那那个人站的位置能确定了。确定之后就可以求下一个了,所以这个前提和结论都成立了。

所以我们只要从后面人站起,数posi个空格站上去就行了。

线段树的话跟求和线段树一样,初始化时全部初始化为1,然后查找的时候可以“二分”查找

*/

时间: 2024-10-10 11:11:13

poj 2828 Buy Tickets (排队问题+线段树)的相关文章

POJ 2828 Buy Tickets (线段树,区间修改)

逆向思维.从最后一位开始考虑,用线段树查询空位置. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include &l

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

题目链接 题意:有N个人排队,给出各个人想插队的位置和标识,要求输出最后的序列. 分析:因为之前的序列会因为插队而变化,如果直接算时间复杂度很高,所以可以用 线段树逆序插入,把序列都插到最后一层,len记录该区间里还剩余多少位置,插入的时候就插到剩余的第几个位置, 比如1,2已经插入了,如果再想插入第3个位置,则实际上插入的是5. 因为是逆序的,所以在3之前除了现在的1,2 还有之前的1,2. 1 #include <iostream> 2 #include <cstdio> 3

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 思路:线段树,从后往前依次插入,插入一个更新一次 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <

POJ 2828 Buy Tickets (线段树 单点更新 插队问题)

题目链接:http://poj.org/problem?id=2828 题意:有个家伙春节买票,闲的没事想了一个让我们做= =!,是酱紫的,有n个人,编号是val,将插队,其序号变为pos,编号的范围[0,n). 刚开始真心没有看出来是个线段树题,要不是在做线段树专题,打死我也不会向线段树上靠拢. 想想这是用线段树解决一个什么样的模型呢? 1:每个人有固定的位置,虽然中途在不停加入,但到最后,一个萝卜一个坑 2:是不停加入成员,而不是改变 3:用线段树记录空余位置 没想到用线段树是我遇到的第一个

poj 2828 buy Tickets 用线段树模拟带插入的队列

Buy Tickets Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2795 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

POJ 2828 Buy Tickets(线段树)

Language: Default Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 13847   Accepted: 6926 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

poj 2828 Buy Tickets【线段树单点更新】【逆序输入】

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16273   Accepted: 8098 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 (线段树 单节点 查询位置更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15533   Accepted: 7759 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