poj-2828 Buy Tickets ***
线段树
//2828
* [这段话转的。。]
* 如果我们从头开始一次做的话,无论是用链表还是数组,肯定会超时(链表寻址时间长,数组移位时间长。)。
* 所以要用一个快速的方法直接找到位置。但是换个角 度,如果我们反过来排,那样的话,我们就知道他所在的
* 精确位置!把存储的结构想象成是链表,插队的人插入后,把他所在的位置从链表中屏蔽掉,然后在新的链 表种
* 继续这样存,这样的话我们就得到了我们想要的顺序!
*
* 按照这种思想,可以用线段树实现。。。
*
*/
#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;
}
也可以用树状数组
【转】
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 ***相关推荐
- poj 2828 Buy Tickets
http://poj.org/problem?id=2828 题意:在一个队列里,有人依次向第pos个位置插入,求最后的序列: 思路:用线段树存储区间内剩余的没有被占的位置,注意插入的时候要从后向前插 ...
- POJ 2828 Buy Tickets 线段树
题目: http://poj.org/problem?id=2828 很巧妙的题,逆序插入线段树,这样元素不用移动.用二叉排序树也能过. 1 #include <stdio.h> 2 #i ...
- POJ 2828. Buy Tickets
链接 http://poj.org/problem?id=2828 题意 有 NNN 个人排队,每一个人都有一个权值 valvalval ,每一个人都会按顺序插入到当前队伍的某一个位置 posposp ...
- POJ 2828 Buy Tickets | 线段树的喵用
题意: 给你n次插队操作,每次两个数,pos,w,意为在pos后插入一个权值为w的数; 最后输出1~n的权值 题解: 首先可以发现,最后一次插入的位置是准确的位置 所以这个就变成了若干个子问题, 所以 ...
- POJ - 2828 Buy Tickets(线段树+思维/Splay+模拟)
题目链接:点击查看 题目大意:给出n个人,一个队列,一开始队列是空的,每个人加入的时候都会插入到指定位置pos的后面,即插队,问最后队列的排列情况是怎么样的 题目分析:一开始很难想到是线段树的题目,毕 ...
- #树状数组#poj 2828 Buy Tickets
题目 输入插队的人和插队的位置,求最终所有人的位置. 分析 树状数组,从后往前(倒推),然后就是要让在前面的次序-1. 代码 #include <cstdio> #include < ...
- 【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)
http://poj.org/problem?id=2828 一开始敲了个splay,直接模拟. tle了.. 常数太大.. 好吧,说是用线段树.. 而且思想很拽.. (貌似很久以前写过貌似的,,) ...
- Buy Tickets(poj 2828)
题意:排队买票,但是 中途 出现插队情况,比如 0 123,代表值为123的人 插入到 0 的位置,如果后面 出现 0 456,那么新的 0的位置就是 456,123就变成是 1的位置了 分析:这道题 ...
- poj Buy Tickets
题目链接:http://poj.org/problem?id=2828 类似的题目:http://www.cnblogs.com/lovychen/p/3674048.html 测试数据: in: 4 ...
- POJ2828 Buy Tickets【线段树,逆序遍历】
刚开始看到题目,想用memmove偷懒,结果TLE,后来查了查,才发现用memmove也是O(n^2)的复杂度... #include <stdio.h> #include <str ...
最新文章
- Nginx源码分析--数据对齐posix_memalign和memalign函数
- 华人世界——客家足迹行
- 事务里面捕获异常_三问Spring事务:解决什么问题?如何解决?存在什么问题?...
- 私有云和公有云的区别_如何理解公有云和私有云
- Go命令行库Cobra的使用
- Spring Aop(九)——基于正则表达式的Pointcut
- 配色方案|平板羽毛集,为你的下个作品做安排
- ajax跨域获取数据后处理,简单实现ajax获取跨域数据
- 跑通通过人脸测试心率程序
- 【机器人】从机械臂示教器导出编码器数据到U盘中的操作步骤
- Dubbo-admin无法显示Group分组信息
- Spring IOC核心源码学习
- ZYNQ7020 FPGA 如何生成从Flash和SD卡启动的镜像文件
- oracle分析函数技术详解(配上开窗函数over())
- Lab multicast msdp
- タイトル キャッスルファンタジア ~エレンシア戦記~リニューアル 艾伦西亚战记(艾伦希亚战记)日文攻略
- 一点笔记,好记性不如烂笔头
- 学习C C++的必备技能(1)
- 东南亚跨境电商ERP怎么选?萌店长ERP,含大数据分析的免费erp系统
- Mac 下 unrar 命令
热门文章
- google us web
- XP系统,CMD窗口总是只显示最后一屏的信息,如何能让全部信息都显示出来呢??
- resource busy and acquire with nowait specified解决方法
- 2分钟学会ajax 入门ajax必备
- 推荐系统与协作过滤面临的主要问题
- phpAdmin修改密码后拒绝访问
- web_find和web_reg_find的用法和区别
- MYSQL----myownstars(102)
- 网站正在建设中提示页面设计欣赏
- [转] Ghost自动安装