poj2828--Buy Tickets
题意 :总共n个人,一个一个的来排队,每个人都有一个要求,要求排到第几个人后面(当然肯定是最后面来的人的要求先满足),每个人有一个对应的val,按顺序输出n的人的val。
用线段树来维护区间剩余的位置数量,,当然必须从最后一个人向前来更新线段树,每次更新之后就把该位置的剩余数量置为0(因为后面的人的要求肯定最先满足嘛)
代码如下:
#include <set> #include <map> #include <cmath> #include <ctime> #include <queue> #include <stack> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef unsigned long long ull; typedef long long ll; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const int maxn = 2e5+10; int seg[maxn<<2],ans[maxn],Pos[maxn],val[maxn],n; void build(int l,int r,int pos) { if (l == r) { seg[pos] = 1; return; } int mid = (l + r) >> 1; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); seg[pos] = seg[pos<<1] + seg[pos<<1|1]; } int update(int l,int r,int pos,int x) { if (l == r) { seg[pos] = 0; return l; } int mid = (l + r) >> 1; int ans; if (seg[pos<<1] >= x) ans = update(l,mid,pos<<1,x); else ans = update(mid+1,r,pos<<1|1,x-seg[pos<<1]); seg[pos] = seg[pos<<1|1] + seg[pos<<1]; return ans; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif while (~scanf ("%d",&n)) { for (int i = 0; i < n; i++) { scanf ("%d%d",Pos+i,val+i); } build(1,n,1); for (int i = n - 1; i >= 0; i--) { int tmp = update(1,n,1,Pos[i]+1); ans[tmp-1] = val[i]; } printf("%d",ans[0]); for (int i = 1; i < n; i++) { printf(" %d",ans[i]); } printf("\n"); } return 0; }