bzoj3262: 陌上花开

一道三维偏序的裸题,其实还是很好想的。(像我一样的萌新先戳-->二维偏序

这次来的是三维了,那么怎么办?二维偏序既可以用CDQ分治,又可以用树状数组,那三维偏序,不就一维排序,一维归并,一维树状数组不就行了?

那么就用树状数组替代之前的sum,因为之前sum就是直接累加了,那用树状数组相当于再加了一层筛选。

 

PS:打cmp的时候,假如不喜欢用a[i].x<a[i].x之类的,最后全部相等时返回false(玄学),不然什么RE,TLE,搞得我一愣一愣的。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;


struct flower
{
    int x,y,z,tot,f;//tot表示x、y、z都一样的花有多少朵,f表示对于这种花,没它漂亮的花数 
}a[110000];int n,len;
void ins(int x,int y,int z)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].z=z;
    a[len].tot=1;a[len].f=0;
}
bool cmp(flower n1,flower n2)
{
         if(n1.x<n2.x)return true;
    else if(n1.x>n2.x)return false;
    else if(n1.y<n2.y)return true;
    else if(n1.y>n2.y)return false;
    else if(n1.z<n2.z)return true;
    else if(n1.z>n2.z)return false;
    return false;
}
void sc()
{
    int x,y,z;
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&x,&y,&z), ins(x,y,z);
        
    sort(a+1,a+len+1,cmp);
    
    n=1;//压缩 
    for(int i=2;i<=len;i++)
        if(a[n].x==a[i].x&&a[n].y==a[i].y&&a[n].z==a[i].z)
            a[n].tot++;
        else
            a[++n]=a[i];
}

//------------sc 第一维排序完成。-------------------- 

int m,s[210000];
int lowbit(int x){return x&-x;}
void add(int x,int k)
{
    while(x<=m)
    {
        s[x]+=k;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int ans=0;
    while(x>=1)
    {
        ans+=s[x];
        x-=lowbit(x);
    }
    return ans;
}

//-----------树状数组解决第三维--------------

flower t[110000];
void cdq(int l,int r)//归并解决第二维,顺便调用树状数组 
{
    if(l==r)return ;
    int mid=(l+r)/2;
    cdq(l,mid);cdq(mid+1,r);
    
    int i=l,j=mid+1,p=l;
    while(i<=mid&&j<=r)
    {
        if(a[i].y<=a[j].y)
            add(a[i].z,a[i].tot), t[p++]=a[i++];
        else
            a[j].f+=getsum(a[j].z), t[p++]=a[j++];
    }
    while(i<=mid)add(a[i].z,a[i].tot), t[p++]=a[i++];
    while(j<=r)a[j].f+=getsum(a[j].z), t[p++]=a[j++];
    
    for(int i=l;i<=mid;i++)add(a[i].z,-a[i].tot);//清空树状数组,这个如果打memset,每重for都一个O(n)会挂
    
    for(int i=l;i<=r;i++)a[i]=t[i];
}

//-------cdq--------------

int ans[110000];
int main()
{    
    scanf("%d%d",&n,&m);
    sc();
    
    memset(s,0,sizeof(s));
    cdq(1,n);
    
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=n;i++)ans[a[i].f+a[i].tot-1]+=a[i].tot;//全部相等,相互之间也算自己更加漂亮 
    for(int i=0;i<len;i++)printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2017-12-12 13:08  AKCqhzdy  阅读(158)  评论(0编辑  收藏  举报