hdu 5126 stars cdq分治

stars

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


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个操作,a=1插入一个点,a=2询问一个子空间中有几个点

用kd树做超时了。网上看到是cdq分治的,看了下ppt。

http://wenku.baidu.com/link?url=VwuZ4ij8GABr5FOVcuU2yyMelwPSa_sXahA9lgVu0bQTrF2J3GuZGgHXE7LinI0-EulsxJJXZ3oMFL4dlIvOZdDlrIudCptcpawthnAMlj3

还看了下别人的解法

最后我的做法大致是这样的,但是比较慢

把一个询问拆成8个查询(容斥咯),用树状数组维护坐标z从0到需要查询位置点的个数,当然z要先离散化。

然后就是用cdq分治,使得每次查询都是有效点了。

思想就是划分一个个集合,使得每个集合里插入点在已经被处理的维度上,坐标都小于询问的坐标值

1. 因为插入和查询的点是有顺序的,所以其实应该看成是四维的。第一次应该先按操作的次序排序(其实就是不用排序了)做cdq分治

2.在cdq分治的第一次里,分治使得点按x轴排序,因为按左右两个部分,可以知道左边部分的次序<右边部分的操作次序,那么把左边的插入和右边的查询放到一起,那么新的集合里在次序这个维度上,查询的就高于插入的了。又因为分治按x排序,那么就可以线性的把新的集合按照x轴大小为第一关键字,次序为第二关键字的方式排序

3.在新的集合里,对y轴进行排序,因为左边的插入操作的点x<右边操作的x,那么满足左边插入的点的y小于右边当前查询的点y,那么在更新树状数组中左边插入点z处值,然后更新查询即可,由于树状数组每次要清空,所以插入的点都需要删除

对于树状数组的清空操作有两种方式:

1. 时间戳标记,用T[],tag,如果T[]=tag说明这个位置的值是新的,否则置成0,让T[]=tag,每次要清空的时候tag++即可

2.删除插入的点

#include<cstdio>
#include<algorithm>
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){}
};
#define maxn 450007
Node star[maxn];
Node star2[maxn];
Node star3[maxn];
int tree[maxn];
int lowbit(int i){
    return i&(-i);
}
void add(int i,int x){
    while(i<maxn){
        tree[i]+=x;
        i+=lowbit(i);
    }
}
int get(int i){
    int ans = 0;
    while(i>0){
        ans += tree[i];
        i -= lowbit(i);
    }
    return ans;
}
int res[maxn];
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);
            }
        }
        for(int i = 0;i < n; i++)
            res[i] = 0;
        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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值