Buy Tickets(线段树) POJ - 2828
有N个人排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍的某一个位置pos。要求把队伍最后的状态输出。
第一行一个整数N,表示n个人 接下来n行,每行两个整数x和val,表示一个标记为val的人,插入到排在第x位置的人的后面。
从前往后,输出所有的val
思路:从后往前读入,记录当前行还有多少个位置没有插入。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstring> #include<stdio.h> #include<algorithm> #include<map> #include<queue> #include<set> #include <sstream> #include<vector> #include<cmath> #include<stack> #include<time.h> #include<ctime> using namespace std; #define inf 1<<30 #define eps 1e-7 #define LD long double #define LL long long #define maxn 10000005 int a[maxn] = {}; int b[maxn] = {}; int ans[maxn] = {}; struct node { int L, R, num; }tree[maxn]; void build(int root, int L, int R) { tree[root].L = L; tree[root].R = R; tree[root].num = (R - L + 1); if (tree[root].L == tree[root].R) { return; } int mid = (L + R) >> 1; build(root << 1, L, mid); build(root << 1 | 1, mid + 1, R); } void update(int root, int step, int val) { if (tree[root].L == tree[root].R) { tree[root].num = 0; ans[tree[root].L] = val; return; } if (tree[root<<1].num >= step)//左子树剩余的位置大于或等于要放的位置 { update(root << 1, step, val); } else { update(root << 1 | 1, step - tree[root << 1].num, val);//要减去左子树的数目 } tree[root].num = tree[root << 1].num + tree[root << 1 | 1].num; } int main() { int n; while (~scanf("%d", &n)) { build(1, 1, n); for (int i = 1; i <= n; i++) { scanf("%d%d", &a[i], &b[i]); } for (int i = n; i >= 1; i--) { update(1, a[i] + 1, b[i]); } for (int i = 1; i <= n; i++) { if (i == 1) { printf("%d", ans[i]); } else { printf(" %d", ans[i]); } } printf("\n"); } }