欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[BZOJ3262]陌上花开(cdq分治)

程序员文章站 2022-05-14 18:49:14
...

照例的传送门piu~
cdq的裸题 这是一道经典的三维偏序问题~~~
一维排序 二维cdq分治 三维树状数组
排序保证了x的有序 其次二分逐层递归 在回溯到该层的时候再进行一次排序保证y的有序性 三维用双指针搞一下放在树状数组里维护
AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,t[200005],ans[100005],m,nn;
struct node{int a,b,c,ans,s;}a[100005],p[100005];
inline bool cmp(node a,node b)
{
    if(a.a==b.a&&a.b==b.b)return a.c<b.c;
    if(a.a==b.a)return a.b<b.b;
    return a.a<b.a;
}
inline bool operator <(node a,node b)
{
    if(a.b==b.b) return a.c<b.c;
    return a.b<b.b;
}
inline int lowbit(int x){return x&-x;}
inline void update(int x,int num){for(int i=x;i<=m;i+=lowbit(i))t[i]+=num;}
inline int ask(int x)
{
    int tmp=0;
    for(int i=x;i;i-=lowbit(i))
        tmp+=t[i];
    return tmp;
}
void solve(int l,int r)
{
    if(l==r) return;
    int mid=l+r>>1;
    solve(l,mid);solve(mid+1,r);
    sort(p+l,p+mid+1);sort(p+mid+1,p+r+1);
    int i=l,j=mid+1;
    while(j<=r)
    {
        while(i<=mid&&p[i].b<=p[j].b)
        {
            update(p[i].c,p[i].s);
            i++;
        }
        p[j].ans+=ask(p[j].c);
        j++;
    }
    for(int j=l;j<i;j++) update(p[j].c,-p[j].s);
}
int main()
{
    scanf("%d%d",&nn,&m);
    for(int i=1;i<=nn;i++) scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
    sort(a+1,a+1+nn,cmp);
    int cnt=0;
    for(int i=1;i<=nn;i++)
    {
        cnt++;
        if(a[i].a!=a[i+1].a||a[i].b!=a[i+1].b||a[i].c!=a[i+1].c)
        {
            p[++n]=a[i];
            p[n].s=cnt;
            cnt=0;
        }
    }
    solve(1,n);
    for(int i=1;i<=n;i++) ans[p[i].ans+p[i].s-1]+=p[i].s;
    for(int i=0;i<nn;i++) printf("%d\n",ans[i]);
    return 0;
}