POJ 2828 线段树 单点更新,单点查询

九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11971839

题意:

n个人

n行:a,b 表示b这个人插队插在a位置

问最后队伍的顺序

思路:

从最后一个人开始,插队过程表示为:

把b放在第a个空位的位置

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <math.h>
#include <queue>
#define N  201000
#define M 2000100
#define inf64 0x7ffffff
#define inf 0x7ffffff
#define ll int
#define L(x) x<<1
#define R(x) x<<1|1
#define Mid(x,y) (x+y)>>1
using namespace std;
inline ll Min(ll a,ll b){return a>b?b:a;}
inline ll Max(ll a,ll b){return a>b?a:b;}

ll len,maxdeep,Query;
struct node{
	int l,r;
	ll sum,num;//sum表示每个人的编号,num表示这个区间剩下的空位
}tree[N*4];

void build(int l,int r,int id){
	tree[id].l = l;	tree[id].r = r;
	tree[id].num = r-l+1;
	if(l==r) return ;
	int mid = Mid(l,r);
	build(l,mid,L(id));	 build(mid+1,r,R(id));

}

void updata_point(int pos,int id, ll data){//单点更新
	if(tree[id].l == tree[id].r)
	{	
		tree[id].num--;
		tree[id].sum = data;
		return ; 
	}
	tree[id].num--;

	if( tree[ L(id) ].num > pos) updata_point(pos,L(id),data);
	else updata_point(pos-tree[L(id)].num,R(id),data);

}

ll query_point(int pos, int id){ //单点询问 sum
	if(tree[id].l == pos && pos == tree[id].r)
		return tree[id].sum ;

	int mid = Mid(tree[id].l, tree[id].r);

	if(pos <= mid) 		return query_point(pos, L(id));
	else				return query_point(pos, R(id));

}

struct quenode{
	int a, b;
}qq[N];
int main(){
	int n,a,b,i;
	while(~scanf("%d",&n)){
		build( 1, n, 1);

		for(i=0;i<n;i++)
			scanf("%d %d",&qq[i].a,&qq[i].b);

		for(i=n-1;i>=0;i--)
		{

			updata_point( qq[i].a, 1, qq[i].b);

		}
		for(i=1;i<n;i++)printf("%d ",query_point(i,1));
		printf("%d\n",query_point(i,1));
	}
	return 0;
}


 

你可能感兴趣的:(POJ 2828 线段树 单点更新,单点查询)