poj2828

来源:互联网 发布:怎么下载淘宝卖家版 编辑:程序博客网 时间:2024/06/10 06:01

题目有难度,线段树。

大致题意:按顺序给定n个人插队时其前方人的个数,并同时给定每个人的ID,令队首元素是第一个人,其前方人个数为0,现在要求按排队的顺序依次输入最终队列的人的编号。

题意很明确。

分析如下:

可令线段树节点结构如下:

struct Node{
 int l,r,value,pos;
}node[Max*3];

其中value为该区间范围内还空余的位置个数,而pos为单位区间的坐标,则有如下式子成立:令输入为d,v

1)若d+1大于node[Lson(po)].value,则应该插入右节点,且权值减少node[Lson(po)].value

2)若d+1小于或等于node[Lson(po)].value,则因该插入左节点

下面是代码:10724K+1500MS

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 200010#define Lson(p) (p<<1)#define Rson(p) (p<<1|1)#define Mid(a,b) ((a+b)>>1)struct Node{int l,r,value,pos;}node[Max*3];int Input[Max][2];int ans[Max];int n;void build_tree(int left,int right,int po){ //创建线段树,注意value为给区间还空余的位置,初始时即为区间长度node[po].l=left,node[po].r=right,node[po].value=right-left+1;if(left==right){node[po].pos=left;return ;}int mid=Mid(left,right);build_tree(left,mid,Lson(po));build_tree(mid+1,right,Rson(po));}void update_tree(int d,int v,int po){ //更新线段树,同时确定最终队列位置node[po].value--;if(node[po].l==node[po].r){ // 若找到最终队列位置ans[node[po].pos]=v; // 赋值编号return ;}if(d>node[Lson(po)].value) //若大于还剩余的空位置,则在右儿子update_tree(d-node[Lson(po)].value,v,Rson(po));else //否则在左儿子update_tree(d,v,Lson(po));}int main(){while(scanf("%d",&n)!=EOF){build_tree(1,n,1); //建树,区间为1——nfor(int i=1;i<=n;i++){ //输入n个人插队信息和个人IDscanf("%d%d",&Input[i][0],&Input[i][1]);Input[i][0]++; //增加1}for(int i=n;i>=1;i--) //逆序更新线段树update_tree(Input[i][0],Input[i][1],1);for(int i=1;i<=n;i++) //按1——n位置输出IDprintf("%d ",ans[i]);printf("\n");}return 0;}



 

0 0
原创粉丝点击