P3810 【模板】三维偏序(陌上花开)

题目背景

这是一道模板题

可以使用bitset,CDQ分治,K-DTree等方式解决。

题目描述

有 nn 个元素,第 ii 个元素有 a_iaib_ibic_ici 三个属性,设 f(i)f(i) 表示满足 a_j leq a_iajai 且 b_j leq b_ibjbi 且 c_j leq c_icjci 的 jj 的数量。

对于 d in [0, n)d[0,n),求 f(i) = df(i)=d 的数量

输入输出格式

输入格式:

第一行两个整数 nn、kk,分别表示元素数量和最大属性值。

之后 nn 行,每行三个整数 a_iaib_ibic_ici,分别表示三个属性值。

输出格式:

输出 nn 行,第 d + 1d+1 行表示 f(i) = df(i)=d 的 ii 的数量。

输入输出样例

输入样例#1: 复制
10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1
输出样例#1: 复制
3
1
3
0
1
0
1
0
0
1

说明

1 leq n leq 100000, 1 leq k leq 2000001n100000,1k200000

//Pro:P3810 【模板】三维偏序(陌上花开)

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

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

const int N=1e5+5;

int n,k;

struct THI
{
    int a,b,c,w,ans;
}thi[N],ele[N];
int m;

bool cmp1(THI A,THI B)
{
    return A.a==B.a?(A.b==B.b?A.c<B.c:A.b<B.b):A.a<B.a;
}

bool cmp2(THI A,THI B)
{
    return A.b==B.b?A.c<B.c:A.b<B.b;
}

#define lowbit(x) x&(-x)
int bit[N<<1],bound;

inline void add(int x,int val)
{
    for(;x<=k;x+=lowbit(x))
        bit[x]+=val;
}

inline int query(int x)
{
    int res=0;
    for(;x;x-=lowbit(x))
        res+=bit[x];
    return res;
}

void divide(int l,int r)
{
    if(l>=r)
        return;
    int mid=(l+r)>>1;
    divide(l,mid),divide(mid+1,r);
    sort(ele+l,ele+mid+1,cmp2);
    sort(ele+mid+1,ele+r+1,cmp2);
    int i=l,j=mid+1;
    for(;j<=r;++j)
    {
        while(ele[i].b<=ele[j].b&&i<=mid)
            add(ele[i].c,ele[i].w),++i;
        ele[j].ans+=query(ele[j].c);
    }
    for(j=l;j<i;++j)
        add(ele[j].c,-ele[j].w);
}

int ans[N];
int main()
{
    n=read(),k=read();
    for(int i=1;i<=n;++i)
        thi[i].a=read(),thi[i].b=read(),thi[i].c=read();
    sort(thi+1,thi+n+1,cmp1);
    for(int i=1,cnt=0;i<=n;++i)
    {
        ++cnt;
        if(thi[i].a!=thi[i+1].a||thi[i].b!=thi[i+1].b||thi[i].c!=thi[i+1].c)
        {
            ele[++m]=thi[i];
            ele[m].w=cnt,
            cnt=0;
        }
    }
    divide(1,m);
    for(int i=1;i<=m;++i)
        ans[ele[i].ans+ele[i].w-1]+=ele[i].w;
    for(int i=0;i<n;++i)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/lovewhy/p/9633897.html