Bzojphp
很显然,咱们只须要考虑单独取线段上方的状况,对于下方的把坐标取反再作一遍便可(由于咱们只关心最终的答案)数组
创建树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左(右)横坐标最大(小)的与它相同的点。code
首先枚举没有取到的颜色,找出全部不包含这种颜色的区间,更新答案。get
接着考虑两个相同颜色的点的贡献,按照纵坐标从大到小枚举全部的点,分别在树状数组和双向链表中删除当前点,并利用这个点左右两边和它颜色相同的点之间的区间内点的个数更新答案。string
#include <cstdio> #include <cstring> #include <algorithm> using std::min; using std::max; using std::sort; using std::swap; using std::unique; using std::lower_bound; typedef long long ll; template<typename T> void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); } while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag; } const int N = 1e5 + 10; int T, n, K, x[N], ans; struct data { int x, y, z, id; } p[N]; int disc[N], t[N];//树状数组 int last[N], l[N], r[N];//双向链表 void add (int x, int y) { while(x <= n + 1) t[x] += y, x += (x & -x); } int query (int x) { int y = 0; while(x) y += t[x], x -= (x & -x); return y; } inline bool cmpx(const data &a, const data &b) { return a.x < b.x; } inline bool cmpy(const data &a, const data &b) { return a.y < b.y; } void update(int l, int r) { if(l > r) return ; int tmp = query(r) - query(l - 1); ans = max(tmp, ans); } void doit () { x[0] = 0, x[n + 1] = n + 1; memset(last, 0, sizeof last), memset(t, 0, sizeof t); sort(&p[1], &p[n + 1], cmpx); for(int i = 1; i <= n; ++i) add(p[i].x, 1); for(int i = 1; i <= n; ++i) { int t = p[i].id, L= last[p[i].z]; l[t] = L, r[t] = n + 1; if(L) r[L] = t; update(x[L] + 1, x[t] - 1); last[p[i].z] = t; } for(int i = 1; i <= K; ++i) update(x[last[i]] + 1, n + 1); sort(&p[1], &p[n + 1], cmpy); for(int i = 1, j = 1; i <= n; ++i) { int t = p[i].id; while(j <= n && p[j].y == p[i].y) add(p[j].x, - 1), ++j; l[r[t]] = l[t], r[l[t]] = r[t]; update(x[l[t]] + 1, x[r[t]] - 1); } } int main () { read(T); while(T--) { ans = 0, read(n), read(K); int m = n; for(int i = 1; i <= n; ++i) read(p[i].x), read(p[i].y), read(p[i].z), p[i].id = i; for(int i = 1; i <= n; ++i) disc[i] = p[i].x; sort(&disc[1], &disc[m + 1]), m = unique(&disc[1], &disc[m + 1]) - disc - 1; for(int i = 1; i <= n; ++i) { p[i].x = lower_bound(&disc[1], &disc[m + 1], p[i].x) - disc; x[i] = p[i].x; } doit(); for(int i = 1; i <= n; ++i) p[i].y = -p[i].y; doit(); printf("%d\n", ans); } return 0; }