寒假第二周学习记录2 HDU5126 CDQ分治

题目链接

大意:在一个三维空间当中,每次进行一个操作,添加一个点或者统计空间中的某一个长方体范围内的所有点

就是用CDQ分治就离线的统计出每个查询的结果
首先我们将每个点z坐标离散化,那么我们就可以利用树状数组统计出每个查询点之前插入的点的z坐标小于等于当前查询的点的个数。
那么我们就是要先将x,y序不大于当前查询,且时序小于当前查询的点先加入的树状数组当中,这一步操作我们需要进行一个嵌套的CDQ分治

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 500005
using namespace std;

struct Node
{
    int x,y,z,p,t;
    Node(){}
    Node( int x , int y , int z , int p , int t )
        :x(x),y(y),z(z),p(p),t(t){}
};

 
Node star[MAX];
Node star2[MAX];
Node star3[MAX];
int tree[MAX];


int lowbit ( int x )
{
    return x&-x;
}

 
void add ( int i ,int x )
{
    while ( i < MAX )
    {
        tree[i] += x;
        i += lowbit(i);
    }
}

 
int get ( int i )

{
    int ans = 0;
    while ( i )
    {
        ans += tree[i];
        i -= lowbit ( i );
    }
    return ans;
}

 
int res[MAX];

 


void CDQ2 ( int l , int r )

{

    if ( l == r ) return;
    int mid = (l+r)/2;

    CDQ2( l , mid );
    CDQ2( mid+1 , r );
    int l1 = l , r1 = mid+1;

    while ( r1 <= r )

    {


        while ( l1 <= mid && star2[l1].y <= star2[r1].y )
        {
            if ( star2[l1].t == 0 ) add ( star2[l1].z , 1 );
            l1++;
        }
        
        if ( star2[r1].t != 0 )
        {
            res[star2[r1].p] += get ( star2[r1].z ) * star2[r1].t;
        }

        r1++;

    }

    
    while ( l1 > l )

    {

        --l1;

        if ( star2[l1].t == 0 ) add ( star2[l1].z , -1 );

    }

    l1 = l , r1 = mid+1;

    for ( int i = l ; i <= r ; i++ )
        if ( (l1 <= mid && star2[l1].y <= star2[r1].y) || r1 > r )
            star3[i] = star2[l1++];
        else star3[i] = star2[r1++];

    for ( int i = l ; i <= r ; i++ )
        star2[i] = star3[i];

}


void CDQ1 ( int l , int r )

{

    if ( l == r ) return;

    int mid = (l+r)/2;
    CDQ1(l,mid);
    CDQ1(mid+1,r);
    int l1 = l , r1 = mid+1 , n = 0;
    while ( r1 <= r )
    {
        while ( star[l1].t != 0 && l1 <= mid ) l1++;
        while ( star[r1].t == 0 && r1 <= r ) r1++;

        if ( r1 > r ) break;
        if ( (star[l1].x <= star[r1].x && l1 <= mid ) || r1 > r )
            star2[n++] = star[l1++];
        else star2[n++] = star[r1++];

    }

 

    if ( n > 0 ) CDQ2(0,n-1);
    l1 = l , r1 = mid+1;

    for ( int i = l ; i <= r ; i++ )
    {
        if ( (star[l1].x <= star[r1].x && l1 <= mid )|| r1 > r )
            star3[i] = star[l1++];
        else star3[i] = star[r1++];

    }

    for ( int i = l ; i <= r ; i++ )
        star[i] = star3[i];
}

 

int compn ( Node a, Node b )

{
    return a.p < b.p;

}


int compz ( Node a , Node b )

{
    return a.z < b.z;

}

 

int main ( )

{

    int t,q,a,x1,y1,z1,x2,y2,z2;
    scanf ( "%d" , &t );
    while ( t-- )
    {

        int n = 0;
        scanf ( "%d" , &q );
        while ( q-- )
        {
            scanf ( "%d" , &a );
            if ( a == 1 )
            {
                scanf ( "%d%d%d" , &x1 , &y1 , &z1 );
                star[n++] = Node ( x1 , y1 , z1 , n , 0 );

            }

            else
            {
                scanf ( "%d%d%d%d%d%d" , &x1 , &y1 , &z1 , &x2 , &y2 , &z2 );
                star[n++] = Node ( x2 , y2 , z2 , n , 1 );
                star[n++] = Node ( x2 , y1-1 , z2 , n , -1 );
                star[n++] = Node ( x1-1 , y2 , z2 , n , -1 );
                star[n++] = Node ( x2 , y2 , z1-1 , n  , -1 );
                star[n++] = Node ( x1-1 , y1-1 , z2 , n , 1 );
                star[n++] = Node ( x1-1 , y2 , z1-1 , n , 1 );
                star[n++] = Node ( x2 , y1-1 , z1-1 , n , 1 );
                star[n++] = Node ( x1-1 , y1-1 , z1-1 , n , -1 );
            }
        }

        memset ( res , 0 , sizeof ( res ));
        sort ( star , star+n , compz );
        a = 1;
        star[n].z = -1;
        for ( int i = 0 ; i < n ; i++ )
            if ( star[i].z != star[i+1].z )
                star[i].z = a++;
            else star[i].z = a;
        sort ( star , star+n , compn );
        CDQ1(0,n-1);
        sort ( star , star+n , compn );
        for ( int i = 0 ; i < n ; i++ )
        {
            if ( star[i].t != 0 )
            {
                int ans = 0;
                for ( int j = 0 ; j < 8 ; j++ )
                    ans += res[i+j];
                printf ( "%d\n" , ans );
                i += 7;
            }
        }
    }
    return 0;

}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值