hdu 4742 Pinball Game 3D 分治+树状数组

离散化x然后用树状数组解决,排序y然后分治解决,z在分治的时候排序解决。

具体:先对y排序,solve(l,r)分成solve(l,mid),solve(mid+1,r), 然后因为是按照y排序,所以l,mid区间内的y值都小于mid+1,r。现在再对z排序,按照顺序以x做关键字插入到树状数组中,那么就可以一起解决l,mid对mid+1,r的影响。

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

const int maxn=1e5+9,mod=1<<30;

int trsum[maxn],trmax[maxn];

int n;

struct P

{

    int x,y,z,id;

}point[maxn],now[maxn];

struct A

{

    int max,sum;

}ans[maxn],tr[maxn];

bool cmpx(const P a,const P b)

{

    return a.x<b.x;

}

bool cmpy(const P a,const P b)

{

    return a.y<b.y;

}

bool cmpz(const P a,const P b)

{

    return a.z<b.z;

}



int lowbit(int x)

{

    return (x&-x);

}



void insert(int x,A tmp)

{

    for(int i=x;i<=n;i+=lowbit(i))

    {

        if(tr[i].max==tmp.max)

        {

            tr[i].sum+=tmp.sum;

            tr[i].sum%=mod;

        }

        else if(tr[i].max<tmp.max)

        {

            tr[i].sum=tmp.sum;

            tr[i].max=tmp.max;

        }

    }

}



A getsum(int x)

{

    A ret;

    ret.max=-1;

    for(int i=x;i>=1;i-=lowbit(i))

    {

        if(tr[i].max>ret.max)

        {

            ret.max=tr[i].max;

            ret.sum=tr[i].sum;

        }

        else if(tr[i].max==ret.max)

        {

            ret.sum+=tr[i].sum;

            ret.sum%=mod;

        }

    }

    return ret;

}



void clear(int x)

{

    for(int i=x;i<=n;i+=lowbit(i))

    {

        tr[i].max=0;

        tr[i].sum=0;

    }

}



void solve(int l,int r)

{

    if(l==r) return ;

    int mid=l+r>>1;

    solve(l,mid);

    for(int i=mid+1;i<=r;i++)

    now[i]=point[i];

    sort(point+l,point+mid+1,cmpz);

    sort(point+mid+1,point+r+1,cmpz);

    for(int i=mid+1,top=l;i<=r;i++)

    {

        while(top<=mid&&point[top].z<=point[i].z)

        {

            insert(point[top].x,ans[point[top].id]);

            top++;

        }

        A ret=getsum(point[i].x);

        ret.max++;

        if(ret.max==ans[point[i].id].max)

        {

            ans[point[i].id].sum+=ret.sum;

            ans[point[i].id].sum%=mod;

        }

        else if(ret.max>ans[point[i].id].max)

        {

            ans[point[i].id]=ret;

        }

    }

    for(int i=l;i<=mid;i++) clear(point[i].x);

    for(int i=mid+1;i<=r;i++)

    point[i]=now[i];

    solve(mid+1,r);

}



int main()

{

//    freopen("in.txt","r",stdin);

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d",&n);

        for(int i=1;i<=n;i++)

        {

            scanf("%d %d %d",&point[i].x,&point[i].y,&point[i].z);

            point[i].id=i;

        }

        sort(point+1,point+1+n,cmpx);

        for(int i=1,xx=point[1].x-1,num=0;i<=n;i++)

        {

            if(point[i].x!=xx) num++,xx=point[i].x;

            point[i].x=num;

        }

        sort(point+1,point+1+n,cmpy);



        for(int i=1;i<=n;i++)

        {

            ans[i].max=1;

            ans[i].sum=1;

        }

        solve(1,n);

        A ret;

        ret.max=-1;

        for(int i=1;i<=n;i++)

        {

            if(ret.max==ans[i].max)

            {

                ret.sum+=ans[i].sum;

                ret.sum%=mod;

            }

            else if(ret.max<ans[i].max)

            {

                ret=ans[i];

            }

        }

        printf("%d %d\n",ret.max,ret.sum);

    }

    return 0;

}


 

 

你可能感兴趣的:(game)