[传送门]
将第二维离散化一下,按第一维从大到小,第二维从小到大,第三维从大到小排序,这样即使第一维相同的情况下也不会重,然后用一棵线段树维护第二维为$I_{i}$时第三维的最大值,插入每一个元素之前先查询$\left[I_{i} + 1, n\right]$的最大值,若查询得到的$x$大于$R_{i}$,$ans++$
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 7; struct P { int f, s, t; inline bool operator < (const P &rhs) const { if (rhs.f == f && rhs.s == s) return t > rhs.t; if (f == rhs.f) return s < rhs.s; return f > rhs.f; } } p[N]; int n, v[N]; struct Seg { #define lp p << 1 #define rp p << 1 | 1 int tree[N << 2]; inline void pushup(int p) { tree[p] = max(tree[lp], tree[rp]); } void update(int p, int l, int r, int pos, int val) { if (l == r) { tree[p] = max(tree[p], val); return; } int mid = l + r >> 1; if (pos <= mid) update(lp, l, mid, pos, val); else update(rp, mid + 1, r, pos, val); pushup(p); } int query(int p, int l, int r, int x, int y) { if (x <= l && y >= r) return tree[p]; int mid = l + r >> 1; int ans = 0; if (x <= mid) ans = max(ans, query(lp, l, mid, x, y)); if (y > mid) ans = max(ans, query(rp, mid + 1, r, x, y)); return ans; } } seg; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &p[i].f); for (int i = 1; i <= n; i++) scanf("%d", &p[i].s), v[i] = p[i].s; for (int i = 1; i <= n; i++) scanf("%d", &p[i].t); sort(v + 1, v + 1 + n); int cnt = unique(v + 1, v + 1 + n) - v - 1; for (int i = 1; i <= n; i++) p[i].s = lower_bound(v + 1, v + 1 + cnt, p[i].s) - v; sort(p + 1, p + n + 1); /*for (int i = 1; i <= n; i++) printf("%d %d %d\n", p[i].f, p[i].s, p[i].t);*/ int ans = 0; for (int i = 1; i <= n; i++) { int temp = seg.query(1, 1, cnt, p[i].s + 1, cnt); if (temp > p[i].t) ans++; seg.update(1, 1, cnt, p[i].s, p[i].t); } printf("%d\n", ans); return 0; }