[JZOJ5456]【NOIP2017提高A组冲刺11.6】奇怪的队列
按身高从小到大排序, 然后得到他的rank, 要不插在队伍前面数第rank+1个空位, 要不就插在从后数的第rank+1位,因为要字典序最小, 所以找到最小的位置插入他。
然后上面的查询操作可以用线段树快速实现。
总复杂度O(NlogN)。
没有输出impossble挂了10分,AK的梦想破灭了233
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define reg register inline int read() { int res=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define N 100005 int n; int tr[N<<2]; #define ls(o) o << 1 #define rs(o) o << 1 | 1 inline void update(int o) { tr[o] = tr[ls(o)] + tr[rs(o)]; } void Build(int l, int r, int o) { if (l == r) { tr[o] = 1; return ; } int mid = l + r >> 1; Build(l, mid, ls(o)); Build(mid + 1, r, rs(o)); update(o); } void change(int l, int r, int o, int pos) { if (l == r) {tr[o] = 0; return ;} int mid = l + r >> 1; if (pos <= mid) change(l, mid, ls(o), pos); else change(mid + 1, r, rs(o), pos); update(o); } int query(int l, int r, int o, int k) { if (l == r) return l; int mid = l + r >> 1; if (tr[ls(o)] >= k) return query(l, mid, ls(o), k); else return query(mid + 1, r, rs(o), k - tr[ls(o)]); } struct date { int h, id; }p[N]; bool cmp(date a, date b) { return a.h < b.h; } int ans[N]; int main() { freopen("queue.in", "r", stdin); freopen("queue.out", "w", stdout); n = read(); for (reg int i = 1 ; i <= n ; i ++) p[i].h = read(), p[i].id = read(); sort(p + 1, p + 1 + n, cmp); Build(1, n, 1); // for (reg int i = 1 ; i <= n ; i ++) printf("%d\n", p[i].h); for (reg int i = 1 ; i <= n ; i ++) { int k1 = query(1, n, 1, p[i].id + 1); int k2 = query(1, n, 1, n - p[i].id - i + 1); if (k1 <= k2) { ans[k1] = p[i].h; change(1, n, 1, k1); } else { ans[k2] = p[i].h; change(1, n, 1, k2); } } for (reg int i = 1 ; i <= n ; i ++) printf("%d ", ans[i]); return 0; }