HDU - 5618 Jam's problem again

题目:给你n个点(x,y,z),让你输出对于每个点(xi,yi,zi)满足xj<=xi&&yj<=yi&&zj<=zi的点的数目

思路:先按照x排序,然后做分治的时候针对y排序,这样会漏掉相等的点对其左边的点的影响,做一下预处理即可

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
//0x3f3f3f3f

const int maxn=1e5+50;
struct Node{
    int x,y,z,id;
}q[maxn],tmp[maxn];
bool cmp1(Node a,Node b){
    if(a.x!=b.x) return a.x<b.x;
    if(a.y!=b.y) return a.y<b.y;
    return a.z<b.z;
}
bool cmp2(Node a,Node b){
    if(a.y!=b.y)
        return a.y<b.y;
    return a.id<b.id;
}
struct BIT{
    int n,b[maxn];
    void init(int _n){
        n=_n;
        mm(b,0);
    }
    void add(int i,int val){
        for(;i<=n;i+=i&(-i))
            b[i]+=val;
    }
    int sum(int i){
        int ret=0;
        for(;i>0;i-=i&(-i))
            ret+=b[i];
        return ret;
    }
}bit;
int ans[maxn];
int n;
void cdq(int L,int R){
    if(L>=R) return;
    int sz=0,mid=(L+R)>>1;
    for(int i=L;i<=mid;i++){
        tmp[sz]=q[i];
        tmp[sz++].id=0;
    }
    for(int i=mid+1;i<=R;i++)
        tmp[sz++]=q[i];
    sort(tmp,tmp+sz,cmp2);
    for(int i=0;i<sz;i++){
        if(tmp[i].id==0) bit.add(tmp[i].z,1);
        else ans[tmp[i].id]+=bit.sum(tmp[i].z);
    }
    for(int i=0;i<sz;i++)
        if(tmp[i].id==0)
            bit.add(tmp[i].z,-1);
    cdq(L,mid);
    cdq(mid+1,R);
}
int main(){

//    freopen("D:\\input.txt","r",stdin);
//    freopen("D:\\output.txt","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        mm(ans,0);
        int mx=1;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
            q[i].id=i;
            mx=max(mx,q[i].z);
        }
        bit.init(mx);
        sort(q+1,q+n+1,cmp1);
        int cnt=0;
        for(int i=n-1;i>=1;i--){
            if(q[i].x==q[i+1].x&&q[i].y==q[i+1].y&&q[i].z==q[i+1].z)
                cnt++;
            else
                cnt=0;
            ans[q[i].id]+=cnt;
        }
        cdq(1,n);
        for(int i=1;i<=n;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值