bzoj千题计划145:bzoj3262: 陌上花开(三维偏序 CDQ分治)

http://www.lydsy.com/JudgeOnline/problem.php?id=3262

 

三维偏序

第一维排序,第二维CDQ分治,第三维树状数组

 

#include<cstdio>
#include<iostream>
#include<algorithm>

#define lowbit(x) x&-x

#define N 100001
#define M 200001

using namespace std;

struct node
{
    int a,b,c;
    int id;
    int cnt;
}e[N],L[N],R[N];

int sum[N],ans[N];

int m;
int c[M];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c))  c=getchar(); 
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

bool cmp1(node p,node q)
{
    if(p.a!=q.a) return p.a<q.a;
    if(p.b!=q.b) return p.b<q.b;
    return p.c<q.c;
}

bool cmp2(node p,node q)
{
    return p.b<q.b;
}

void change(int x,int y)
{
    while(x<=m)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}

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

void solve(int l,int r)
{
    if(l==r) 
    {
        sum[e[l].id]+=e[l].cnt-1;
        return;
    }
    int mid=l+r>>1;
    for(int i=l;i<=mid;++i) L[i]=e[i];
    for(int i=mid+1;i<=r;++i) R[i]=e[i];
    sort(L+l,L+mid+1,cmp2);
    sort(R+mid+1,R+r+1,cmp2);
    int i=l,j=mid+1;
    for(;j<=r;++j)
    {
        while(i<=mid && L[i].b<=R[j].b)
        {
            change(L[i].c,L[i].cnt);
            i++;
        }
        sum[R[j].id]+=query(R[j].c);
    }
    for(int k=l;k<i;++k) change(L[k].c,-L[k].cnt);
    solve(l,mid);
    solve(mid+1,r);
}

int main()
{
    int n;
    read(n); read(m);
    for(int i=1;i<=n;++i)
    {
        read(e[i].a);
        read(e[i].b);
        read(e[i].c);
    }
    sort(e+1,e+n+1,cmp1);
    for(int i=1;i<=n;++i) e[i].id=i;
    int tot=0;
    for(int i=1;i<=n;++i)
    {
        if(e[i].a!=e[i-1].a || e[i].b!=e[i-1].b || e[i].c!=e[i-1].c)
        {
            e[++tot].cnt=1;
            e[tot].a=e[i].a;
            e[tot].b=e[i].b;
            e[tot].c=e[i].c;
            e[tot].id=tot;
        }
        else e[tot].cnt++;
    }
    solve(1,tot);
    for(int i=1;i<=tot;++i) ans[sum[i]]+=e[i].cnt;
    for(int i=0;i<n;++i) cout<<ans[i]<<'\n';
}

 

posted @ 2017-12-18 17:14  TRTTG  阅读(199)  评论(0编辑  收藏  举报