题意:已知每个人的独一无二的身高以及排在他前面或者后面比他高的人数,问身高字典序最小的排法
分析:首先对身高从矮到高排序,那么可以知道每个人有多少人的身高比他高,那么取较小值(k[i], n - i - k[i]),若后者小于0则无解。然后可以理解为每个人前面要留出p + 1个位子给高个的人,可用线段树维护,s[rt] 表示当前线段还能空出的位子数。当然也能用树状数组+二分查找位子的方法。
/************************************************ * Author :Running_Time * Created Time :2015/9/28 星期一 12:01:30 * File Name :J.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-8; struct ST { int s[N<<2], ans[N]; void push_up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; } void build(int l, int r, int rt) { if (l == r) { s[rt] = 1; return ; } int mid = (l + r) >> 1; build (lson); build (rson); push_up (rt); } void updata(int p, int v, int l, int r, int rt) { if (l == r) { ans[l] = v; s[rt] = 0; return ; } int mid = (l + r) >> 1; if (p <= s[rt<<1]) { updata (p, v, lson); } else updata (p - s[rt<<1], v, rson); push_up (rt); } }st; struct PP { int h, k; bool operator < (const PP &r) const { return h < r.h; } }p[N]; int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { int n; scanf ("%d", &n); for (int i=1; i<=n; ++i) { scanf ("%d%d", &p[i].h, &p[i].k); } sort (p+1, p+1+n); st.build (1, n, 1); bool flag = true; for (int i=1; i<=n; ++i) { int pos = min (p[i].k, n - i - p[i].k); if (pos < 0) { flag = false; break; } st.updata (pos + 1, p[i].h, 1, n, 1); } printf ("Case #%d: ", ++cas); if (!flag) puts ("impossible"); else { for (int i=1; i<=n; ++i) { printf ("%d%c", st.ans[i], i == n ? ' ' : ' '); } } } return 0; }
/************************************************ * Author :Running_Time * Created Time :2015/9/28 星期一 15:48:08 * File Name :J_BIT.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-8; struct PP { int h, k; bool operator < (const PP &r) const { return h < r.h; } }p[N]; struct BIT { int c[N], SZ; void init(int n) { memset (c, 0, sizeof (c)); SZ = n; } void updata(int i, int x) { while (i <= SZ) { c[i] += x; i += i & (-i); } } int query(int i) { int ret = 0; while (i) { ret += c[i]; i -= i & (-i); } return ret; } int my_binary_search(int l, int r, int k) { while (l <= r) { int mid = (l + r) >> 1; if (mid - query (mid) < k) l = mid + 1; else if (mid - query (mid) == k) { if (query (mid) - query (mid - 1) == 1) r = mid - 1; else return mid; } else r = mid - 1; } return -1; } }bit; int ans[N]; int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { int n; scanf ("%d", &n); for (int i=1; i<=n; ++i) { scanf ("%d%d", &p[i].h, &p[i].k); } sort (p+1, p+1+n); bit.init (n); bool flag = true; for (int i=1; i<=n; ++i) { int pos = min (p[i].k, n - i - p[i].k); if (pos < 0) { flag = false; break; } int x = bit.my_binary_search (1, n, pos + 1); ans[x] = p[i].h; bit.updata (x, 1); } printf ("Case #%d: ", ++cas); if (!flag) puts ("impossible"); else { for (int i=1; i<=n; ++i) { printf ("%d%c", ans[i], i == n ? ' ' : ' '); } } } return 0; }