• 三维偏序(陌上花开)


    题目描述

    题解:

    这是cdq分治模板题。

    前置:cdq分治。

    好像是一位大佬搞出来的神奇分治,可以直接干掉一层树形结构。

    其实实现还是比较简单的。

    对于区间(l,r),我们先处理(l,mid)和(mid+1,r),然后处理左右区间之间产生的影响。

    具体顺序看题目而定。

    比如本题,我们可以先令a有序,然后分治。

    每次处理影响时先排序,然后双指针分别扫。

    由于aj<=ai,bj<=bi,cj<=ci,我们在刚开始已经令a有序,所以在保证bj<=bi时将c扔到数据结构中(我用的是树状数组,线段树可以解决更多情况)。

    然后每次加一下当前c的前缀和就行了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,k;
    struct node
    {
        int a,b,c,f,w;
        void read(){a=rd(),b=rd(),c=rd();}
    }p[N],tmp[N];
    bool cmp(node x,node y)
    {
        if(x.a!=y.a)return x.a<y.a;
        if(x.b!=y.b)return x.b<y.b;
        return x.c<y.c;
    }
    struct BIT
    {
        int g[N<<1];
        void up(int x,int d)
        {
            if(!x)return ;
            while(x<=200000)
            {
                g[x]+=d;
                x+=(x&(-x));
            }
        }
        int down(int x)
        {
            if(!x)return 0;
            int ret = 0;
            while(x)
            {
                ret+=g[x];
                x-=(x&(-x));
            }
            return ret;
        }
    }bit;
    void Sort(int l,int r)
    {
        int mid = (l+r)>>1;
        int i = l,j = mid+1,k = l;
        while(i<=mid&&j<=r)
        {
            while(p[i].b<=p[j].b&&i<=mid&&j<=r)
            {
                tmp[k] = p[i];
                i++,k++;
            }
            while(p[i].b>p[j].b&&i<=mid&&j<=r)
            {
                tmp[k] = p[j];
                j++,k++;
            }
        }
        while(i<=mid)
        {
            tmp[k]=p[i];
            i++,k++;
        }
        while(j<=r)
        {
            tmp[k]=p[j];
            j++,k++;
        }
        for(i=l;i<=r;i++)p[i]=tmp[i];
    }
    int ans[N];
    void cdq(int l,int r)
    {
        if(l==r)return ;
        int mid = (l+r)>>1;
        cdq(l,mid);cdq(mid+1,r);
        int i,j;
        for(i=l,j=mid+1;j<=r;j++)
        {
            while(p[i].b<=p[j].b&&i<=mid)
            {
                bit.up(p[i].c,p[i].w);
                i++;
            }
            p[j].f+=bit.down(p[j].c);
        }
        for(i=i-1;i>=l;i--)bit.up(p[i].c,-p[i].w);
        Sort(l,r);
    }
    bool vmp(node x,node y)
    {
        return x.a==y.a&&x.b==y.b&&x.c==y.c;
    }
    int main()
    {
        n=rd(),k=rd();
        for(int i=1;i<=n;i++)
            tmp[i].read();
        sort(tmp+1,tmp+1+n,cmp);
        int k=0;
        tmp[0].a=-1;
        for(int i=1;i<=n;i++)
        {
            if(vmp(tmp[i],tmp[i-1]))
            {
                p[k].w++;
            }else
            {
                k++;
                p[k] = tmp[i];
                p[k].w = 1;
            }
        }
        cdq(1,k);
        for(int i=1;i<=k;i++)ans[p[i].f+p[i].w-1]+=p[i].w;
        for(int i=0;i<n;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    【干货】MySQL数据库开发规范
    springboot入门
    移动端可拖拽效果
    利用视口单位实现适配布局
    最新前端开发工程师面试题
    12个HTML和CSS必须知道的重点难点问题
    win10升级后蓝牙不见了,设备管理器里没有,多了个串行控制器里的未知USB设备?
    安装vue-cli时出现的错误,cmd 卡住
    svg 认识及动画
    banner图片全屏显示
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10143270.html
Copyright © 2020-2023  润新知