P3810 【模板】三维偏序(陌上花开)
题目背景
这是一道模板题
可以使用bitset,CDQ分治,K-DTree等方式解决。
题目描述
有 nn 个元素,第 ii 个元素有 a_iai、b_ibi、c_ici 三个属性,设 f(i)f(i) 表示满足 a_j \leq a_iaj≤ai 且 b_j \leq b_ibj≤bi 且 c_j \leq c_icj≤ci 的 jj 的数量。
对于 d \in [0, n)d∈[0,n),求 f(i) = df(i)=d 的数量
输入输出格式
输入格式:
第一行两个整数 nn、kk,分别表示元素数量和最大属性值。
之后 nn 行,每行三个整数 a_iai、b_ibi、c_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 2000001≤n≤100000,1≤k≤200000
//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\n",ans[i]); return 0; }