[HDU 5618]Jam's problem again——CDQ分治

来源:互联网 发布:火焰纹章 网络 编辑:程序博客网 时间:2024/05/14 10:58

题目传送门

解题思路

本题为裸的三维偏序,直接用CDQ分治解。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100005;struct jz{    int x,y,z,id;    bool operator==(const jz&b){return x==b.x&&y==b.y&&z==b.z;}}q[maxn],t[maxn];int tt,n,m,tot,ans[maxn],a[maxn];inline int _read(){    int num=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();    return num;}bool cmp1(const jz &a,const jz &b){    if (a.x<b.x) return 1;    if (a.x==b.x&&a.y<b.y) return 1;    if (a.x==b.x&&a.y==b.y&&a.z<b.z) return 1;    if (a.x==b.x&&a.y==b.y&&a.z==b.z&&a.id<b.id) return 1;    return 0;}bool cmp2(const jz &a,const jz &b){    if (a.y<b.y) return 1;    if (a.y==b.y&&a.id<b.id) return 1;    return 0;}int lowbit(int x){return x&(-x);}void change(int x,int y){    while (x<=m){        a[x]+=y;        x+=lowbit(x);    }}int ask(int x){    int num=0;    while (x>0){        num+=a[x];        x-=lowbit(x);    }    return num;}void cdq(int L,int R){    if (L==R) return;    int mid=L+(R-L>>1);    for (int i=L;i<=mid;i++) t[i]=q[i],t[i].id=0;    for (int i=mid+1;i<=R;i++) t[i]=q[i];    sort(t+L,t+R+1,cmp2);    for (int i=L;i<=R;i++)    if (t[i].id) ans[t[i].id]+=ask(t[i].z);    else change(t[i].z,1);    for (int i=L;i<=R;i++) if (!t[i].id)change(t[i].z,-1);    cdq(L,mid);cdq(mid+1,R);}int main(){    freopen("exam.in","r",stdin);    freopen("exam.out","w",stdout);    tt=_read();    while (tt--){        memset(ans,0,sizeof(ans));        n=_read();m=0;tot=0;        for (int i=1;i<=n;i++){            q[i].x=_read();q[i].y=_read();q[i].z=_read();            q[i].id=i;m=max(q[i].z,m);        }        sort(q+1,q+1+n,cmp1);        for (int i=n-1;i>0;i--){            if (q[i]==q[i+1]) tot++;else tot=0;            ans[q[i].id]=tot;        }        cdq(1,n);        for (int i=1;i<=n;i++) printf("%d\n",ans[i]);    }    return 0;}
1 0