zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    EF 使用 oracle
    mysql安装笔记
    解决问题
    第四次冲刺
    第三次冲刺
    SQA
    第二次冲刺
    第一次冲刺,求进步
    Scrum _GoodJob
    我对git 、github的初印象
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8027247.html
Copyright © 2011-2022 走看看