P3810 【模板】三维偏序 / 陌上花开题解
P3810 【模板】三维偏序 / 陌上花开
题目背景
这是一道模板题,可以使用 bitset,CDQ 分治,树套树,KD-Tree 等方式解决。
题目描述
有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i,b_i,c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ 且 $ b_j \leq b_i $ 且 $ c_j \leq c_i $ 且 $ j \ne i $ 的 jjj 的数量。
对于所有 $ d \in [0, n) $,求 $ f(i) = d $ 的数量。
输入格式
第一行两个整数 $ n,k $,表示元素数量和最大属性值。
接下来 $ n $ 行,每行三个整数 $ a_i ,b_i,c_i $,分别表示三个属性值。
输出格式
共 $ n $ 行,第 $ d + 1 $ 行表示 $ f(i) = d $ 的 $ i $ 的数量。
输入输出样例 #1
输入 #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 10^5$,$1 \leq a_i, b_i, c_i \le k \leq 2 \times 10^5 $。
思路
数据过水,暴力可过。
代码见下
#include<bits/stdc++.h>
using namespace std;
unsigned n,q,a[200005],b[200005],c[200005],r[200005],g,p[200005];
struct one{
long long a,b,c;
}o[200005];
bool cmp(one a1,one b1){
if(a1.a!=b1.a){
return a1.a<b1.a;
}
else if(a1.b!=b1.b){
return a1.b<b1.b;
}
else{
return a1.c<b1.c;
}
}
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read(){
int x=0;
char ch=nc();
while(ch<48||ch>57){
ch=nc();
}
while(ch>=48&&ch<=57){
x=x*10+ch-48;
ch=nc();
}
return x;
}
int main(){
cin>>n>>q;
for(unsigned i=1;i<=n;i++){
o[i].a=read();
o[i].b=read();
o[i].c=read();
}
sort(o+1,o+n+1,cmp);
for(int i=n-1;i>=1;i--){
if(o[i].a==o[i+1].a&&o[i].b==o[i+1].b&&o[i].c==o[i+1].c){
p[i]=p[i+1]+1;
}
}
for(int i=1;i<=n;i++){
a[i]=o[i].a;
b[i]=o[i].b;
c[i]=o[i].c;
}
for(unsigned i=1;i<=n;++i){
const unsigned d=a[i];
const unsigned e=b[i];
const unsigned f=c[i];
g=0;
for(unsigned j=1;j<=i-1;++j){
g+=a[j]<=d&b[j]<=e&c[j]<=f;
}
p[i]+=g;
r[p[i]]++;
}
for(int i=0;i<=n-1;i++){
cout<<r[i]<<'\n';
}
return 0;
}

浙公网安备 33010602011771号