bzoj3262 陌上花开 cdq分治(入门)

题目传送门

思路:cdq分治处理偏序关系的模板题,主要就是学cdq分治吧,还在入门中。

  代码其实也很好理解,记得树状数组操作的上限是 z的最大值,不是n的最大值,这个细节wa了好久。

#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=100010;
struct node{
    int x,y,z,id;
    node(){}
    node(int x,int y,int z,int id):x(x),y(y),z(z),id(id){}
}a[maxn],b[maxn];
int ans[maxn],bit[maxn<<1],pr[maxn];
int n,k,maxd;
inline void add(int x,int v){
    while(x<=maxd){//切记  上限不是n,是z的最大值 
        bit[x]+=v;
        x+= x & -x;
    }
}
inline int sum(int x){
    int ces=0;
    while(x>0){
        ces+=bit[x];
        x -= x & -x;
    }
    return ces;
}
bool cmpall(const node &a,const 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 cmpy(const node &a,const node &b){
    if(a.y!=b.y)return a.y<b.y;
    return a.id<b.id;
}
inline void cdq(int l,int r){
    if(l==r)return ;
    int mid=(l+r)>>1;
    int cc=0;
    for(int i=l;i<=mid;i++)
    {
        b[++cc]=a[i];
        b[cc].id=0,b[cc].x=0;
    }
    for(int i=mid+1;i<=r;i++)
    {
        b[++cc]=a[i],b[cc].x=0;
    }
    sort(b+1,b+1+cc,cmpy);
    for(int i=1;i<=cc;i++)
    {
        if(b[i].id==0){
            add(b[i].z,1);
        }else{
            ans[b[i].id]+=sum(b[i].z);
        }
    }
    for(int i=1;i<=cc;i++)
    {
        if(b[i].id==0)add(b[i].z,-1);
    }
    cdq(l,mid),cdq(mid+1,r);
    return ;
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
        maxd=max(maxd,a[i].z);
        a[i].id=i;
    }
    sort(a+1,a+1+n,cmpall);
    int cnt=0;
    for(int i=n;i>=1;i--)
    {
        if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y&&a[i].z==a[i+1].z)
        {
            cnt++;
        }else cnt=0;
        ans[a[i].id]+=cnt;
    }
    cdq(1,n);
    for(int i=1;i<=n;i++)
    {
        pr[ans[i]]++;
    }
    for(int i=0;i<n;i++)
    {
        printf("%d\n",pr[i]);
    }
}

 

posted @ 2018-12-03 23:03  光芒万丈小太阳  阅读(150)  评论(0编辑  收藏  举报