POJ 2828 Buy Tickets(排队问题,线段树应用)

ACM

题目地址:POJ 2828 Buy Tickets

题意: 

排队买票时候插队。 

给出一些数对,分别代表某个人的想要插入的位置Pos_i和他的Val_i,求出最后的队列的val顺序。

分析: 

也是一道非常巧妙的题目。 

刚開始天真的以为sort一下即可了。wa了一发后发现我错了... 

原来能够非常巧妙的用线段树做。因为某个人想要插入posi位置,插入后他就在posi位置上了,可是可能其它人会插到他前面来,他的位置就会变成[在他后面且插在他位置及曾经的人数]+posi了。 

假设这样就開始求了,当然用线段树就能够做了,就跟求逆序数对一样。 

可是我们能够反着来考虑,仅仅要从后面開始站,如果后面的人都已经站在正确的位置上了,那么到那个人站的时候,如今的位置上已经都是后面的那些人了,仅仅要数posi个空格,那那个人站的位置能确定了。确定之后就能够求下一个了,所以这个前提和结论都成立了。

所以我们仅仅要从后面人站起,数posi个空格站上去即可了。 

线段树的话跟求和线段树一样,初始化时所有初始化为1,然后查找的时候能够“二分”查找,巧妙地找到须要的位置,详细见代码,尽管代码非常挫。 

代码用了输入输出外挂来提速,没加也能过的,请无视。

代码:

/*
* Author: illuz <iilluzen[at]gmail.com>
* Blog: http://blog.csdn.net/hcbbt
* File: 2828.cpp
* Create Date: 2014-08-05 20:16:28
* Descripton:
*/ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define lson(x) ((x) << 1)
#define rson(x) ((x) << 1 | 1) typedef long long ll; const int N = 200000;
const int ROOT = 1; // below is sement point updated version
struct seg {
ll w;
}; struct segment_tree {
seg node[N << 2]; void update(int pos) {
node[pos].w = node[lson(pos)].w + node[rson(pos)].w;
} void build(int l, int r, int pos) {
if (l == r) {
node[pos].w = 1;
return;
}
int m = (l + r) >> 1;
build(l, m, lson(pos));
build(m + 1, r, rson(pos));
update(pos);
} int remove(int l, int r, int pos, ll x) { // 删掉并查询
if (l == r) {
node[pos].w = 0;
return l;
}
int m = (l + r) >> 1;
int res;
if (x < node[lson(pos)].w) // 再此二分查找
res = remove(l, m, lson(pos), x);
else
res = remove(m + 1, r, rson(pos), x - node[lson(pos)].w);
update(pos);
return res;
}
} sgm; int Scan() {
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-')
flag = 1;
else if(ch >= '0' && ch <= '9')
res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
} void Out(int a) {
if(a > 9)
Out(a / 10);
putchar(a % 10 + '0');
} int a[2][N], n;
int ans[N]; int main() {
while (~scanf("%d", &n)) {
repf (i, 0, n - 1) {
a[0][i] = Scan();
a[1][i] = Scan();
}
sgm.build(1, n, ROOT);
for (int i = n - 1; i >= 0; i--) {
ans[sgm.remove(1, n, ROOT, a[0][i])] = a[1][i];
}
repf (i, 1, n) {
if (i != 1)
printf(" ");
Out(ans[i]);
}
printf("\n");
}
return 0;
}

POJ 2828 Buy Tickets(排队问题,线段树应用)的更多相关文章

  1. poj 2828 Buy Tickets 【线段树点更新】

    题目:id=2828" target="_blank">poj 2828 Buy Tickets 题意:有n个人排队,每一个人有一个价值和要插的位置,然后当要插的位 ...

  2. POJ 2828 Buy Tickets(线段树 树状数组/单点更新)

    题目链接: 传送门 Buy Tickets Time Limit: 4000MS     Memory Limit: 65536K Description Railway tickets were d ...

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

    http://poj.org/problem?id=2828 题意 排队买票,依次给出当前人要插队的位置,每个人有个编号,然后问你最后整个的序列是什么? 分析 最后一个人的要插入的位置是确定的,所以逆 ...

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

    Buy Tickets Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2 ...

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

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16273   Accepted: 8098 Desc ...

  6. poj 2828 Buy Tickets (线段树 单节点 查询位置更新)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15533   Accepted: 7759 Desc ...

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

    题目链接 题意:有N个人排队,给出各个人想插队的位置和标识,要求输出最后的序列. 分析:因为之前的序列会因为插队而变化,如果直接算时间复杂度很高,所以可以用 线段树逆序插入,把序列都插到最后一层,le ...

  8. POJ 2828 Buy Tickets (线段树 || 树状数组)

    题目大意 一些小朋友在排队,每次来一个人,第i个人会插到第x个人的后面.权值为y.保证x∈[0,i-1]. 按照最后的队伍顺序,依次输出每个人的权值. 解题分析 好气吖.本来是在做splay练习,然后 ...

  9. poj 2828 Buy Tickets【线段树 单点更新】

    倒着插,先不理解意思,后来看一篇题解说模拟一下 手动模拟一下就好理解了----- 不过话说一直写挫---一直改啊----- 好心塞------ #include <cstdio> #inc ...

  10. 【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)

    http://poj.org/problem?id=2828 一开始敲了个splay,直接模拟. tle了.. 常数太大.. 好吧,说是用线段树.. 而且思想很拽.. (貌似很久以前写过貌似的,,) ...

随机推荐

  1. [Leetcode]-ReverseLinkedList

    题目:单链表取反 #include <stdlib.h> #include <stdio.h> typedef struct node *list; typedef struc ...

  2. 使用JS模拟出Map对象

    近期要做的一个项目,支持方提供的一个Map方法,用着相当能够,功能稍有欠缺,因此我为之做了扩展,下面是代码: function Map() { this.elements = new Array(); ...

  3. Redshift扩容及踩到的坑

    下午发现redshift集群已经没有什么空间了.删掉一些不须要的暂时表也仅仅降到86%左右,为了能放下这两天的数据必须扩容了 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  4. poj 2369 Permutations 更换水称号

    寻找循环节求lcm够了,如果答案是12345应该输出1.这是下一个洞. #include<iostream> #include<cstdio> #include<cstr ...

  5. hdu3501

    要我们求小于n并且不与n互素的数字的和, 那么可以转化为1->(n-1)的和减去小于n且与n互素的数字的和 首先,有gcd(n,i)=1, 那么gcd(n,n-i)=1, 这是因为如果a%s=0 ...

  6. Netty In Action中国版 - 第二章:第一Netty程序

    本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本 ...

  7. Codeforces 32E Hide-and-Seek 乞讨2关于镜面反射点 计算几何

    主题链接:点击打开链接 必须指出的是,反射镜和2个人共线是不是障碍,但根据该壁其他情况 #include<cstdio> #include<iostream> #include ...

  8. JavaScript动态更改页面元素

    通过JavaScript动态变化HTML元素 至HTML加元 首先需要创建一个标签,然后添加到标签中的相应的内容.然后创建添加到相应的位置好标签. <!DOCTYPE html PUBLIC & ...

  9. [Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻

    原文:[Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻 [说明] 本文说明如何在 Windows Phone 应用程式中,加入市集搜寻的功能,主要使用了 Mar ...

  10. 理解和运用javascript中的call及apply

    call是为了改变函数上下文context而存在的,换言之,就是改变函数内部this的指向.因为javascript存在[定义时上下文],[运行时上下文]及[上下文]是可以改变的.例如:var fun ...