POJ 2828-Buy Tickets(线段树)
题意:
有n个人,每人有一定的价值,给n个安排,每次安排有两个数 p,v p是这个人前面人的个数 (直接插在第p个人后面其他人后移),v是它的价值,n个安排后 求最终的价值序列。
分析:
越在后面的安排越是他的最终位置,所有我们要从后向前做,每次找前面有p个空位的位置,找到后空位减一,用线段树来维护区间的空位数。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<1|1 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) #define N 200010 const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int num[N<<2],a[N],v[N],n,pos; void build(int l,int r,int rt){ num[rt]=(r-l)+1;//初始全部空位 if(l==r)return; int m=(l+r)>>1; build(lson); build(rson); } void update(int s,int l,int r,int rt){ num[rt]--;//对应区间空位减一 if(l==r){ pos=l; return; } int m=(l+r)>>1; if(s<=num[rt<<1])update(s,lson);//先找左子树 else{ s-=num[rt<<1]; update(s,rson);//再找右子树 所需空位-左子树空位 } } int main() { int tmp[N]; while(~scanf("%d",&n)){ build(1,n,1); for(int i=0;i<n;++i){ scanf("%d%d",&a[i],&v[i]); } for(int i=n-1;i>=0;i--){ update(a[i]+1,1,n,1);//自己需要一个空位 tmp[pos]=v[i]; } for(int i=1;i<=n;++i) printf("%d ",tmp[i]); printf("\n"); } return 0; }