HDU 5126 stars (CDQ分治)

stars

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 689    Accepted Submission(s): 196



Problem Description
John loves to see the sky. A day has Q times. Each time John will find a new star in the sky, or he wants to know how many stars between (x1,y1,z1) and (x2,y2,z2) .
 

Input
The first line contains a single integer T(1T10) (the data for Q>100 less than 6 cases),, indicating the number of test cases.
The first line contains an integer Q(1Q50000) ,indicating how many times in a day.
Next Q lines contain some integers, first input an integer A(1A2) .If A=1 then input 3 integers x, y and z, indicating a coordinate of one star.. If A=2 then input 6 integers x1,y1,z1,x2,y2,z2(1x,y,z,x1,y1,z1,x2,y2,z2109,x1x2,y1y2,z1z2) .
 

Output
For each “A=2”,output an integer means how many stars in such a section.
 

Sample Input
  
  
2 11 1 1 1 1 2 1 1 1 1 1 1 1 2 2 2 1 1 1 2 2 1 1 1 2 2 2 1 3 3 3 1 4 4 4 1 5 5 5 1 6 6 6 2 1 1 1 6 6 6 2 3 3 3 6 6 6 11 1 1 1 1 2 1 1 1 1 1 1 1 2 2 2 1 1 1 2 2 1 1 1 2 2 2 1 3 3 3 1 4 4 4 1 5 5 5 1 6 6 6 2 1 1 1 6 6 6 2 3 3 3 6 6 6
 

Sample Output
  
  
1 3 7 4 1 3 7 4 题意: 给出m次操作,每次可以在三维空间中增加一个点,或者询问两个矩形间的满足偏序要求的星星有多少个 最近看了qsc大牛的教学视屏,自己试着写了一发 CDQ分治来做大概是这么回事,还是基于一种分治思想,对于时间维先排好序,分治时间维,再对x维排序,分治x维,这样就成功的将问题降到了只剩二维,接下来就只需要对y进行排序,和对z进行离散处理和树状数组计数了。 感觉就是分治分治排序树状数组,主题思想还是分治。
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f

struct node
{
    int x,y,z;
    int kind,id;
    node(){}
    node(int _x,int _y,int _z,int _k,int _id):x(_x),y(_y),z(_z),kind(_k),id(_id){}
};

vector<node>q,q1,q2;
vector<int>mdzz;
int ans[500005],c[500005];

void init()
{
    q.clear();
    mdzz.clear();
    memset(c,0,sizeof c);
}

bool cmp(node A,node B)
{
    if(A.x==B.x) return A.id<B.id;
    return A.x<B.x;
}

bool cmp1(node A,node B)
{
    if(A.y==B.y) return A.id<B.id;
    return A.y<B.y;
}

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

void update(int x,int val)
{
    for(;x<=mdzz.size();x+=lowbit(x)) c[x]+=val;
}

int query(int x)
{
    int sum=0;
    for(;x>0;x-=lowbit(x)) sum+=c[x];
    return sum;
}

void countstar()
{
    for(int i=0;i<q2.size();i++)
    {
        if(q2[i].kind==0) update(q2[i].z,1);
        else ans[q2[i].id]+=q2[i].kind*query(q2[i].z);
    }
    for(int i=0;i<q2.size();i++)
    {
        if(q2[i].kind==0) update(q2[i].z,-1);
    }
}

void CDQ1(int l,int r)
{
    if(l>=r) return ;
    int mid=l+r>>1;
    CDQ1(l,mid);
    q2.clear();
    for(int i=l;i<=mid;i++)
    {
        if(q1[i].kind==0) q2.push_back(q1[i]);
    }
    for(int i=mid+1;i<=r;i++)
    {
        if(q1[i].kind!=0) q2.push_back(q1[i]);
    }
    sort(q2.begin(),q2.end(),cmp1);
    countstar();
    CDQ1(mid+1,r);
}

void CDQ(int l,int r)
{
    if(l>=r) return ;
    int mid=l+r>>1;
    CDQ(l,mid);
    q1.clear();
    for(int i=l;i<=mid;i++)
    {
        if(q[i].kind==0) q1.push_back(q[i]);
    }
    for(int i=mid+1;i<=r;i++)
    {
        if(q[i].kind!=0) q1.push_back(q[i]);
    }
    sort(q1.begin(),q1.end(),cmp);
    CDQ1(0,q1.size()-1);
    CDQ(mid+1,r);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        init();
        for(int i=0;i<n;i++)
        {
            int op;
            scanf("%d",&op);
            if(op==1)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                q.push_back(node(x,y,z,0,i));
                mdzz.push_back(z);
                ans[i]=-1;
            }
            else
            {
                int x1,y1,z1,x2,y2,z2;
                scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                x1--,y1--,z1--;
                q.push_back(node(x1,y1,z1,-1,i));
                q.push_back(node(x2,y2,z2,1,i));
                q.push_back(node(x1,y2,z2,-1,i));
                q.push_back(node(x2,y1,z2,-1,i));
                q.push_back(node(x2,y2,z1,-1,i));
                q.push_back(node(x2,y1,z1,1,i));
                q.push_back(node(x1,y2,z1,1,i));
                q.push_back(node(x1,y1,z2,1,i));
                mdzz.push_back(z1);
                mdzz.push_back(z2);
                ans[i]=0;
            }
        }
        sort(mdzz.begin(),mdzz.end());
        mdzz.erase(unique(mdzz.begin(),mdzz.end()),mdzz.end());
        for(int i=0;i<q.size();i++)
        {
            q[i].z=(lower_bound(mdzz.begin(),mdzz.end(),q[i].z)-mdzz.begin())+1;
        }
        CDQ(0,q.size()-1);
        for(int i=0;i<n;i++)
        {
            if(ans[i]!=-1) printf("%d\n",ans[i]);
        }
    }
    return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值