POJ 2828 Buy Tickets(线段树:查找并更新从左到右第i个1)
来源:互联网 发布:大数据职位体系 编辑:程序博客网 时间:2024/05/17 01:27
POJ 2828 Buy Tickets(线段树:查找并更新从左到右第i个1)
http://poj.org/problem?id=2828
题意:
火车站有n个人排队,他们是按顺序到达的,但是他们乱插队。每个人有两个值pos[i]和val[i]。比如现在第5个人来了,他的pos[5]值为3,那么他就会插队到当前第3个人位置的后面(第0个人是售票窗口)。依次给出所有人的pos和val值,要你最终按所有人的位置顺序输出val值。
分析:
本题的解法类似于POJ 2182:
http://blog.csdn.net/u013480600/article/details/21574467
我们维护一棵线段树,然后该树的所有叶子节点的初值为1(每个元素的值为1,比如第r元素值为1,说明位置r目前还有1个坑),当我们插入一个人到位置r时候,就把控制区间[r, r]的该叶子节点的sum值置为0(说明当前r位置已经被人占了不能再用了,且这个人永远不会变动位置了。因为我们是从后往前逆向插入的,所以最后一个人的位置始终是固定的)。
首先最后来到的那个观众肯定是位于pos[n]+1位置的,所以我们用线段树的query操作找到sum==pos[n]+1的那个叶节点,这个叶节点就是我们应该插入的位置,修改该位置的sum值为0,val值为v[n],并更新线段树即可。
接下来我们要找到n-1观众的位置,假设pos[n-1]+1=x,那么这个x的含义是我们没有插入第n个人的时候整个队列中的第x个空位(即线段树中的第x个1的位置),现在因为已经插入了第n个人,所以我们要自己越过这第n个人的位置,假设他不存在还没有插入。
所以我们只要找到线段树中的所有叶节点中,sum值正好为1,且正好这个1是所有现存1的叶子节点中的第x个时,那么这个叶子节点就是n-1人应该在的位置。即我们在处理第i个人的时候,自动忽略了那些已经值为0的叶节点,因为他们在第i个人之后,实际上他们在i插入的时候还不存在。
AC代码:1750ms
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 200000;struct node{ int p; int v;}nodes[MAXN];int val[MAXN*4];int sum[MAXN*4];int cnt,n;#define lson i*2,l,m#define rson i*2+1,m+1,rvoid PushUp(int i){ sum[i]=sum[i*2]+sum[i*2+1];}void build(int i,int l,int r){ if(l==r) { sum[i]=1; return ; } int m =(r+l)/2; build(lson); build(rson); PushUp(i);}void print(int i,int l,int r){ if(l==r) { cnt++; printf("%d",val[i]); if(cnt<n) printf(" "); else printf("\n"); return ; } int m =(r+l)/2; print(lson); print(rson);}void update(int p,int v,int i,int l,int r){ if(l==r) { if(sum[i]==1) { sum[i]=0; val[i]=v; } return ; } int m=(l+r)/2; if(p<=sum[i*2])update(p,v,lson); else update(p-sum[i*2],v,rson); PushUp(i);}int main(){ while(scanf("%d",&n)==1&&n) { cnt=0; build(1,1,n); for(int i=1;i<=n;i++) { scanf("%d%d",&nodes[i].p,&nodes[i].v); nodes[i].p++; } for(int i=n;i>=1;i--) { int p=nodes[i].p; int v=nodes[i].v; update(p,v,1,1,n); } print(1,1,n); } return 0;}
- POJ 2828 Buy Tickets(线段树:查找并更新从左到右第i个1)
- POJ 2828 Buy Tickets(线段树—查找并更新从左到右的第i个1)
- poj 2828 Buy Tickets(线段树单点更新)
- poj 2828 Buy Tickets (线段树---单点更新)
- POJ - 2828 Buy Tickets(线段树单点更新)
- POJ 题目2828 Buy Tickets(线段树单点更新)
- POJ 2828 Buy Tickets(线段树--单点更新)
- POJ 2828 Buy Tickets (线段树:单点更新)
- POJ 2828 Buy Tickets(线段树-单点更新)
- POJ 2828-Buy Tickets(线段树单点更新-插队)
- POJ 2828 Buy Tickets(线段树的单点更新)
- poj 2828 Buy Tickets(线段树)
- POJ 2828 Buy Tickets(线段树)
- poj 2828 Buy Tickets(线段树)
- POJ 2828 Buy Tickets(线段树)
- poj 2828 Buy Tickets (线段树)
- POJ 2828--Buy Tickets(线段树)
- POJ 2828 Buy Tickets(线段树)
- Input子系统 阻塞调用
- Android自动化测试中AccessibilityService获取控件信息(3)
- mediawiki的logo图片修改不了!
- ubuntu安装QQ2013
- 003_009 Python 转化时区信息设置
- POJ 2828 Buy Tickets(线段树:查找并更新从左到右第i个1)
- 【Alex_笔记】CSharp--值类型和引用类型
- Memcached源码分析之do_item_alloc操作
- npm设置代理 以及 重定向
- 永久隐藏任务栏
- learning perl(一)标量 数组 哈希
- 常用排序
- 亲情进程间传递打开的fd
- GCC编辑器