版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82925776
题目链接:点击这里
解题思路:将一个轴(z轴)从小到大排序(排序过程注意x,y也要讨论).之后的问题就变成了在排序数组中找到最长上升序列问题了.
然后用CDQ分治 + 树状数组,x轴排序,y轴用树状数组维护,就ok了.
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int mx = 1e5 + 10;
const int mod = 1<<30;
typedef long long ll;
int n,ret,m;
int py[mx],cnt,siz[mx];
struct data
{
int lon,siz;
}dat[mx],ans,dp[mx];
struct node
{
int x,y,z;
int id;
bool operator < (node A)const
{
return x < A.x;
}
}s[mx],tep[mx];
bool cmp(node A,node B)
{
if(A.z==B.z){
if(A.x==B.x) return A.y < B.y;
return A.x < B.x;
}
return A.z < B.z;
}
void up(data& A,data B)
{
if(B.lon>A.lon) A = B;
else if(B.lon==A.lon) A.siz = (A.siz+B.siz)%mod;
}
void add(int x,int id){
data tmp = dp[id];
while(x<=n){
up(dat[x],tmp);
x += x&(-x);
}
}
data Get(int x)
{
data tmp = {0,0};
while(x){
up(tmp,dat[x]);
x -= x&(-x);
}
tmp.lon++;
return tmp;
}
void clr(int x)
{
while(x<=n){
dat[x].lon = dat[x].siz = 0;
x += x&(-x);
}
}
int Rank(int x)
{
return lower_bound(py+1,py+m,x)-py;
}
void cdq(int l,int r)
{
if(l==r) return ;
int mid = (l+r)>>1;
int i = l,j = mid + 1;
cdq(l,mid);
for(int k=l;k<=r;k++) tep[k] = s[k];
sort(tep+l,tep+mid+1);
sort(tep+mid+1,tep+r+1);
while(j<=r){
while(i<=mid&&tep[i].x<=tep[j].x)
{
add(Rank(tep[i].y),tep[i].id);
i++;
}
data no = Get(Rank(tep[j].y));
up(dp[tep[j].id],no);
j++;
}
for(i=l;i<=mid&&tep[r].x>=tep[i].x;i++) clr(Rank(tep[i].y));
cdq(mid+1,r);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ans.lon = ans.siz = 0,m = 2;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
py[i] = s[i].y;
dp[i].lon = 1,dp[i].siz = 1;
}
sort(s+1,s+1+n,cmp);
for(int i=1;i<=n;i++) s[i].id = i;
sort(py+1,py+1+n);
for(int i=2;i<=n;i++) if(py[i]!=py[i-1]) py[m++] = py[i];
cdq(1,n);
for(int i=1;i<=n;i++) up(ans,dp[i]);
printf("%d %d\n",ans.lon,ans.siz);
}
return 0;
}