线段树

//2828

View Code

/*
* [这段话转的。。]
* 如果我们从头开始一次做的话,无论是用链表还是数组,肯定会超时(链表寻址时间长,数组移位时间长。)。
* 所以要用一个快速的方法直接找到位置。但是换个角 度,如果我们反过来排,那样的话,我们就知道他所在的
* 精确位置!把存储的结构想象成是链表,插队的人插入后,把他所在的位置从链表中屏蔽掉,然后在新的链 表种
* 继续这样存,这样的话我们就得到了我们想要的顺序!
*
* 按照这种思想,可以用线段树实现。。。
*
*/

#include <cstdio>
using namespace std;

const int MAXN = 200000 + 5;
int n, p[MAXN], v[MAXN];
int ans[MAXN], tail;

struct node{
int l, r;
int num, value; //num:当前时刻,该区间有多少空位,, value:该区间的人的value(只叶子节点有意义)
};
node tree[MAXN * 3]; //注意*3! 否则 RE!!

//建树
void build(int i, int l, int r){
tree[i].l = l; tree[i].r = r;
tree[i].num = r - l + 1; //初始时的空位数

if(l == r) return;
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1 | 1, mid+1, r);
}

//……
void insert(int i, int p, int v){
tree[i].num--; //没到一个区间,该区间的空位数-1,
// 因为既然到达该区间,则该人要么在该区间,要么在该区间的子区间。都导致区间的空位数-1

if(tree[i].l == tree[i].r){ //只叶子节点的value有意义
tree[i].value = v;
return ;
}

if(tree[i<<1].num > p)
insert(i<<1, p, v);
else
insert(i<<1 | 1, p-tree[i<<1].num, v); //减去左子区间的空位数
}

void cal(int i){
if(tree[i].l == tree[i].r){
ans[tail++] = tree[i].value;
return;
}
cal(i<<1);
cal(i<<1 | 1);

}

int main(){
while(scanf("%d", &n) == 1){
for(int i=0; i<n; i++)
scanf("%d %d", &p[i], &v[i]);

build(1, 1, n);

for(int i=n-1; i>=0; i--){
insert(1, p[i], v[i]);
}

tail = 0;
cal(1);

printf("%d", ans[0]);
for(int i=1; i<n; i++){
printf(" %d", ans[i]);
}
printf("\n");

}

return 0;
}

也可以用树状数组

【转】

View Code

/*
PKU 2828:树状数组+二分,一开始一直在想如何处理后面加进来的人,即正着考虑的话,当前的信息是不能得到答案的,突然想起以前一道题,发现只要倒着处理的话,就能很好得解决这个问题了,因为最后一个插进来的人所插入的位置就是这个人最后所站的位置。具体的做法就是先在树状数组的每个位置上都加1,表示一开始每个位置上都站着一个人,每次二分查找该人所站的位置,找到后把这个位置的1减掉,相当于这个位置被占据了,那么下次要得到相同人数的话位置就相应得往后移了。
*/
#include <cstdio>
#include <memory.h>
using namespace std;

const int N = 200005;
int _n;
int res[N];
int c[N];
struct Peo {
int pos, val;
}peo[N];

int lowbit( int n )
{
return n & (-n);
}

void modify( int n, int delta )
{
while( n <= _n )
{
c[n] += delta;
n += lowbit(n);
}
}

int sum( int n )
{
int ret = 0;
while( n != 0 )
{
ret += c[n];
n -= lowbit(n);
}
return ret;
}

int getRank( int pos ) {
int mid, begin = 1, end = _n;
while ( begin < end ) {
mid = (begin + end) / 2;
if ( sum(mid) >= pos ) end = mid;
else begin = mid + 1;
}
return end;
}

int main()
{
while ( scanf("%d", &_n) != EOF ) {
int i;
memset(c, 0, sizeof(c));
for (i=1; i<=_n; ++i) {
scanf("%d %d", &peo[i].pos, &peo[i].val);
peo[i].pos++;
modify(i, 1);
}
for (i=_n; i>=1; --i) {
int now = getRank(peo[i].pos);
res[now] = peo[i].val;
modify(now, -1);
}
for (i=1; i<_n; ++i) {
if (i == 1) printf("%d", res[i]);
else printf(" %d", res[i]);
}
printf(" %d\n", res[_n]);
}
return 0;
}

poj-2828 Buy Tickets ***相关推荐

  1. poj 2828 Buy Tickets

    http://poj.org/problem?id=2828 题意:在一个队列里,有人依次向第pos个位置插入,求最后的序列: 思路:用线段树存储区间内剩余的没有被占的位置,注意插入的时候要从后向前插 ...

  2. POJ 2828 Buy Tickets 线段树

    题目: http://poj.org/problem?id=2828 很巧妙的题,逆序插入线段树,这样元素不用移动.用二叉排序树也能过. 1 #include <stdio.h> 2 #i ...

  3. POJ 2828. Buy Tickets

    链接 http://poj.org/problem?id=2828 题意 有 NNN 个人排队,每一个人都有一个权值 valvalval ,每一个人都会按顺序插入到当前队伍的某一个位置 posposp ...

  4. POJ 2828 Buy Tickets | 线段树的喵用

    题意: 给你n次插队操作,每次两个数,pos,w,意为在pos后插入一个权值为w的数; 最后输出1~n的权值 题解: 首先可以发现,最后一次插入的位置是准确的位置 所以这个就变成了若干个子问题, 所以 ...

  5. POJ - 2828 Buy Tickets(线段树+思维/Splay+模拟)

    题目链接:点击查看 题目大意:给出n个人,一个队列,一开始队列是空的,每个人加入的时候都会插入到指定位置pos的后面,即插队,问最后队列的排列情况是怎么样的 题目分析:一开始很难想到是线段树的题目,毕 ...

  6. #树状数组#poj 2828 Buy Tickets

    题目 输入插队的人和插队的位置,求最终所有人的位置. 分析 树状数组,从后往前(倒推),然后就是要让在前面的次序-1. 代码 #include <cstdio> #include < ...

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

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

  8. Buy Tickets(poj 2828)

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

  9. poj Buy Tickets

    题目链接:http://poj.org/problem?id=2828 类似的题目:http://www.cnblogs.com/lovychen/p/3674048.html 测试数据: in: 4 ...

  10. POJ2828 Buy Tickets【线段树,逆序遍历】

    刚开始看到题目,想用memmove偷懒,结果TLE,后来查了查,才发现用memmove也是O(n^2)的复杂度... #include <stdio.h> #include <str ...

最新文章

  1. Nginx源码分析--数据对齐posix_memalign和memalign函数
  2. 华人世界——客家足迹行
  3. 事务里面捕获异常_三问Spring事务:解决什么问题?如何解决?存在什么问题?...
  4. 私有云和公有云的区别_如何理解公有云和私有云
  5. Go命令行库Cobra的使用
  6. Spring Aop(九)——基于正则表达式的Pointcut
  7. 配色方案|平板羽毛集,为你的下个作品做安排
  8. ajax跨域获取数据后处理,简单实现ajax获取跨域数据
  9. 跑通通过人脸测试心率程序
  10. 【机器人】从机械臂示教器导出编码器数据到U盘中的操作步骤
  11. Dubbo-admin无法显示Group分组信息
  12. Spring IOC核心源码学习
  13. ZYNQ7020 FPGA 如何生成从Flash和SD卡启动的镜像文件
  14. oracle分析函数技术详解(配上开窗函数over())
  15. Lab multicast msdp
  16. タイトル キャッスルファンタジア ~エレンシア戦記~リニューアル 艾伦西亚战记(艾伦希亚战记)日文攻略
  17. 一点笔记,好记性不如烂笔头
  18. 学习C C++的必备技能(1)
  19. 东南亚跨境电商ERP怎么选?萌店长ERP,含大数据分析的免费erp系统
  20. Mac 下 unrar 命令

热门文章

  1. google us web
  2. XP系统,CMD窗口总是只显示最后一屏的信息,如何能让全部信息都显示出来呢??
  3. resource busy and acquire with nowait specified解决方法
  4. 2分钟学会ajax 入门ajax必备
  5. 推荐系统与协作过滤面临的主要问题
  6. phpAdmin修改密码后拒绝访问
  7. web_find和web_reg_find的用法和区别
  8. MYSQL----myownstars(102)
  9. 网站正在建设中提示页面设计欣赏
  10. [转] Ghost自动安装