题意:三维LIS。给出空间的n个点,求出最长的序列和方案数,要求序列的后一个点三个坐标都不小于前一个点。
先排序掉一维,然后剩下两维分治, 用一个带长度和方案数的结构体树状数组维护。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
#define maxn 100005
#define mod (1LL<<30)
struct node {
int id;
int x, y, z;
bool operator == (const node &a) const {
return x == a.x && y == a.y && z == a.z;
}
}qu[maxn], tmp[maxn];
struct Node {
int len, num;
} ans[maxn], c[maxn];
int n;
bool cmp1 (const node &a, const node &b) {
if (a.z != b.z)
return a.z < b.z;
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
bool cmp2 (const node &a, const node &b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int lowbit (int x) {
return x&(-x);
}
void judge (Node &a, Node b) {
if (a.len < b.len) a = b;
else if (a.len == b.len) a.num += b.num, a.num %= mod;
}
void update (int x, Node tmp) {
for (int i = x; i < maxn; i += lowbit (i)) {
judge (c[i], tmp);
}
}
Node query (int x) {
Node ans = (Node) {0, 0};
for (int i = x; i > 0; i -= lowbit (i)) {
judge (ans, c[i]);
}
return ans;
}
void clear (int x) {
for (int i = x; i < maxn; i += lowbit (i))
c[i] = (Node) {0, 0};
}
void solve (int l, int r) {
if (l == r)
return ;
int mid = (l+r)>>1;
solve (l, mid);
for (int i = l; i <= r; i++) tmp[i] = qu[i];
sort (tmp+l, tmp+mid+1, cmp2);
sort (tmp+mid+1, tmp+r+1, cmp2);
int L = l;
for (int i = mid+1; i <= r; i++) {
while (L <= mid && tmp[L].x <= tmp[i].x) {
update (tmp[L].y, ans[tmp[L].id]);
L++;
}
Node cur = query (tmp[i].y);
cur.len++;
judge (ans[tmp[i].id], cur);
}
for (int i = l; i <= mid; i++) {
clear (tmp[i].y);
}
solve (mid+1, r);
}
int num[maxn], tot;
int gg[maxn];
void lisanhua () {
sort (num, num+tot);
int cnt = 0;
for (int i = 0; i < tot; i++) {
if (!i || num[i] != num[i-1]) gg[cnt++] = num[i];
}
for (int i = 1; i <= n; i++) {
qu[i].y = lower_bound (gg, gg+cnt, qu[i].y)-gg+1;
}
}
int scan () {
char ch=' ';
while(ch<'0'||ch>'9')ch=getchar();
int x=0;
while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
return x;
}
int main () {
int t;
scanf ("%d", &t);
while (t--) {
memset (c, 0, sizeof c);
tot = 0;
scanf ("%d", &n);
for (int i = 1; i <= n; i++) ans[i] = (Node) {1, 1};
for (int i = 1; i <= n; i++) {
qu[i].x = scan (), qu[i].y = scan (), qu[i].z = scan ();
num[tot++] = qu[i].y;
qu[i].id = i;
}
lisanhua ();
sort (qu+1, qu+1+n, cmp1);
solve (1, n);
int Max = 0;
Node res = (Node) {0, 0};
for (int i = 1; i <= n; i++) judge (res, ans[i]);
printf ("%d %d\n", res.len, res.num);
}
return 0;
}