posted on 2019-08-27 17:42:41
#22606. 我继续吃柠檬
————二维偏序
题目描述
柠檬树上有 n 颗柠檬,编号从 1 到 n,每一颗柠檬都具有美感 \(a_i\) 和酸度 \(b_i\) 两个属性。
现在我想从树上摘柠檬吃,设每颗柠檬能带给我的快乐值为 \(e_i\),\(e_i\) 等于除了柠檬 i 自身以外,美感和酸度均不大于柠檬 i 的柠檬数量,即:
\(e_i=\sum_j1\),其中 \(1\leq j \leq n\) 且 \(i \neq j\) 且 \(a_j \leq a_i\) 且 \(b_j \leq b_i\)。
请求出每颗柠檬能带给我的快乐值。
输入格式
从标准输入读入数据。
输入第一行是一个整数 n(\(1 \leq n \leq 200000\)),代表柠檬数量。
第二行是 n 个整数 \(a_i\)(\(1 \leq a_i \leq 10^9\)),代表每个柠檬的美感。
第三行是 n 个整数 \(b_i\)(\(1 \leq b_i \leq 10^9\)),代表每个柠檬的酸度。
输出格式
输出到标准输出。
输出 n 行,第 i 行为第 i 颗柠檬能带给我的快乐值。
样例1输入
12 9 10 6 1 3 11 2 7 8 4 12 5 12 4 1 3 6 11 7 2 5 10 8 9
样例1输出
8 3 0 0 1 9 1 1 3 3 7 3
解:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; int n, ans[200005]; struct lemon { int by, sr, id, sm; } ln[200005], t[200005]; int cmp(lemon a, lemon b) { if (a.by != b.by) return a.by < b.by; return a.sr < b.sr; } void mergesort(int l, int r) { int mid = l + (r - l) / 2; if (l == r) return; mergesort(l, mid); mergesort(mid + 1, r); int total = 0, cnt = 0; for (int i = l, j = mid + 1; i <= mid || j <= r;) { if (i <= mid && ln[i].sr <= ln[j].sr) { t[total++] = ln[i]; cnt++; i++; } else { if (j > r && i <= mid) { t[total++] = ln[i]; cnt++; i++; } else { ans[ln[j].id] += cnt; t[total++] = ln[j]; j++; } } } for (int i = l; i <= r; i++) { ln[i] = t[i - l]; } } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> ln[i].by; for (int i = 1; i <= n; i++) { cin >> ln[i].sr; ln[i].id = i; } sort(ln + 1, ln + 1 + n, cmp); for (int i = 1; i <= n; i++) { int num = 0; for (int j = i + 1; ln[j].by == ln[i].by && ln[j].sr == ln[i].sr; j++) { ln[i].sm++; } for (int j = i, mus = 0; j <= i + ln[i].sm, mus <= ln[i].sm; j++, mus++) { ans[ln[j].id] += ln[i].sm - mus; } i += ln[i].sm; } mergesort(1, n); for (int i = 1; i <= n; i++) cout << ans[i] << endl; return 0; }