HDU 4742 Pinball Game 3D(CDQ分治)

Description
给出n个三维点对(x,y,z),求三维非严格最长上升子序列长度和最长上升子序列数量
Input
第一行为一整数T表示用例组数,每组用例第一行为一整数n表示点数,之后n行每行三个整数x,y,z表示一个点(T<=3,n<=10^5,0<=x,y,z<=2^30)
Output
对于每组用例,输出两个整数分别表示三维非严格最长上升子序列长度和最长上升子序列数量(数量结果模2^30)
Sample Input
2
3
2 0 0
0 1 0
0 1 1
5
3 0 0
0 1 0
0 0 1
0 2 2
3 3 3
Sample Output
2 1
3 2
Solution
三维LIS,CDQ分治即可,至于数量在状态转移的过程中多开一维记录即可
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 111111
#define mod (1<<30)
typedef pair<int,int>P;
int n,h[maxn],tot;
P dp[maxn];
struct node
{
    int x,y,z,id;
}p[maxn];
int cmpx(node a,node b)
{
    if(a.x!=b.x)return a.x<b.x;
    if(a.y!=b.y)return a.y<b.y;
    return a.z<b.z;
}
int cmpy(node a,node b)
{
    if(a.y!=b.y)return a.y<b.y;
    return a.z<b.z;
}
void modify(P &dp1,P &dp2)
{
    if(dp1.first<dp2.first)dp1=dp2;
    else if(dp1.first==dp2.first)dp1.second+=dp2.second;
}
struct BIT 
{
    #define lowbit(x) (x&(-x))
    P b[maxn];
    void init()
    {
        for(int i=0;i<maxn;i++)
            b[i]=make_pair(0,0);
    }
    void update(int x,P &v)
    {
        while(x<=n)
        {
            modify(b[x],v);
            x+=lowbit(x);
        }
    }
    P query(int x)
    {
        P ans=make_pair(0,0);
        while(x)
        {
            modify(ans,b[x]);
            x-=lowbit(x);
        }
        return ans;
    }
    void clear(int x)
    {
        while(x<=n)
        {
            b[x]=make_pair(0,0);
            x+=lowbit(x);
        }
    }
}bit;
void CDQ(int l,int r)
{
    if(l==r)return ;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    sort(p+l,p+mid+1,cmpy);
    sort(p+mid+1,p+r+1,cmpy);
    int j=l;
    for(int i=mid+1;i<=r;i++)
    {   
        for(;j<=mid&&p[j].y<=p[i].y;j++)
            bit.update(p[j].z,dp[p[j].id]);
        P temp=bit.query(p[i].z);
        temp.first++;
        modify(dp[p[i].id],temp);
    }
    for(int i=l;i<j;i++)bit.clear(p[i].z);
    sort(p+mid+1,p+r+1,cmpx);  
    CDQ(mid+1,r);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        tot=0,bit.init();
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
            h[++tot]=p[i].z;
        }
        sort(p+1,p+n+1,cmpx);
        sort(h+1,h+tot+1);
        for(int i=1;i<=n;i++)
        {
            p[i].z=lower_bound(h+1,h+tot+1,p[i].z)-h;
            p[i].id=i;
            dp[i]=make_pair(1,1);
        }
        CDQ(1,n);
        P ans=make_pair(0,0);
        for(int i=1;i<=n;i++)modify(ans,dp[i]);
        printf("%d %d\n",ans.first,ans.second%mod);
    }
    return 0;
}

你可能感兴趣的:(HDU 4742 Pinball Game 3D(CDQ分治))