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;
}


 

 

posted @ 2013-10-09 19:48  pangbangb  阅读(342)  评论(1编辑  收藏  举报