zoukankan      html  css  js  c++  java
  • 【BZOJ】3262: 陌上花开

    【题意】三维偏序,给定n个点(x,y,z),求每个点和(0,0,0)组成空间中的点数,有重点。1<=x,y,z<=2*10^5,1<=n<=10^5。

    【算法】CDQ分治+树状数组

    【题解】CDQ算法知识

    三维偏序,一维排序扫描线(x),一维树状数组前缀和(y),一维CDQ分治(z作为时间维)。

    1.将重复的点统一为一个并附加数量的属性。

    2.将z作为时间维,按照z-x-y排序后对z重编号为1~n(时间维不允许重复数字,否则无法分治),再按x-y-z排序(时间维依然要作为第三关键字排序)。

    3.CDQ分治,最后得到的a[]数组自然变成了按照z-x-y排序的结果

    4.统计答案,d[ans[i]+a[i].w-1]+=a[i].w。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #define lowbit(x) (x&-x)
    using namespace std;
    int read(){
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    const int maxn=200010;
    struct cyc{int t,x,y,w;}a[maxn],b[maxn];
    int n,m,c[maxn],d[maxn],ans[maxn];
    bool cmp(cyc a,cyc b){return a.x<b.x||(a.x==b.x&&a.y<b.y)||(a.x==b.x&&a.y==b.y&&a.t<b.t);}
    bool cmp2(cyc a,cyc b){return a.t<b.t||(a.t==b.t&&a.x<b.x)||(a.t==b.t&&a.x==b.x&&a.y<b.y);}
    void modify(int x,int k){for(int i=x;i<=m;i+=lowbit(i))c[i]+=k;}
    int find(int x){int as=0;for(int i=x;i>=1;i-=lowbit(i))as+=c[i];return as;}
    void CDQ(int l,int r){
        if(l==r)return;
        int mid=(l+r)>>1;
        for(int i=l;i<=r;i++)if(a[i].t<=mid)modify(a[i].y,a[i].w);else ans[a[i].t]+=find(a[i].y);
        for(int i=l;i<=r;i++)if(a[i].t<=mid)modify(a[i].y,-a[i].w);
        int x1=l-1,x2=mid;
        for(int i=l;i<=r;i++)if(a[i].t<=mid)b[++x1]=a[i];else b[++x2]=a[i];
        for(int i=l;i<=r;i++)a[i]=b[i];
        CDQ(l,mid);CDQ(mid+1,r);
    }
    int main(){
        n=read();m=read();int N=n;
        for(int i=1;i<=n;i++)a[i].t=read(),a[i].x=read(),a[i].y=read();
        sort(a+1,a+n+1,cmp2);
        int tot=0,num=0;
        for(int i=1;i<=n;i++){
            num++;
            if(a[i].t!=a[i+1].t||a[i].x!=a[i+1].x||a[i].y!=a[i+1].y){
                b[++tot]=a[i];b[tot].w=num;
                num=0;
            }
        }
        n=tot;
        for(int i=1;i<=n;i++)a[i]=b[i],a[i].t=i;
        sort(a+1,a+n+1,cmp);
        CDQ(1,n);
        for(int i=1;i<=n;i++)d[ans[i]+a[i].w-1]+=a[i].w;
        for(int i=0;i<N;i++)printf("%d
    ",d[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    毕业进度10
    毕业进度9
    毕业进度8
    毕业设计7
    毕业设计6
    java算法每日一练2021/1/26
    java算法每日一练2021/1/23
    java算法每日一练2021/1/21
    java算法每日一练2021/1/20
    java算法每日一练2021-01-18
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8059923.html
Copyright © 2011-2022 走看看