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

照例的传送门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;
}

猜你喜欢

转载自blog.csdn.net/Ltb_Sjy1120/article/details/81393072