11---
22layout : post
3- title : " 题解:【模板】三维偏序 / 陌上花开 "
4- subtitle : " 树套树三维偏序"
5- date : 2026-2-16
3+ title : " 高维偏序 "
4+ subtitle : " 树套树三维偏序/高维偏序 "
5+ date : 2026-2-17
66author : " TH911"
77header-img : " img/2024/10/006.jpeg"
88header-mask : 0.4
@@ -11,15 +11,190 @@ tags:
1111 - 题解
1212 - 树套树
1313 - 省选/NOI−
14+ - 未完
1415words :
16+ - 题解:题解:【模板】三维偏序 / 陌上花开
1517---
1618
17- > [ 题目传送门] ( https://www.luogu.com.cn/problem/P3810 )
19+ > [ 不知道从哪里下的 PDF] ( https://th911.dpdns.org/file/2026/02/FHR-分块bitset求高维偏序.pdf ) ,感觉写的很好。
20+
21+ 处理偏序问题时,需要考虑两个元素完全相同的情况,这时需要该元素 $a$ 的统计个数 $\textit{cnt}$,然后统计满足偏序条件元素个数 $x$,则 $a$ 的答案为 $x-1$,同时直接做 $\textit{cnt}$ 的贡献。
22+
23+ # 一维偏序
24+
25+ 排序即可。
26+
27+ # 二维偏序
28+
29+ 排序之后树状数组统计即可。
30+
31+ 比如逆序对。
32+
33+ # 三维偏序
34+
35+ > [ luogu P3810 【模板】三维偏序 / 陌上花开] ( https://www.luogu.com.cn/problem/P3810 )
1836>
19- > 有 $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 $ 的 $j$ 的数量。
37+ > 有 $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 $ 的 $j$ 的数量。
2038>
2139> 对于所有 $ d \in [ 0, n) $,求 $ f(i) = d $ 的数量。
2240>
2341> 设 $a_i,b_i,c_i$ 最大值为 $k$,$1\leq n\leq10^5,1\leq a_i,b_i,c_i\leq k\leq2\times10^5$。
2442
25- # 一维偏序
43+ 考虑先按照 $a$ 排序,之后就是要求满足 $b_j\leq b_i,c_j\leq c_i$,这就是一个二维限制问题。
44+
45+ 考虑树套树解决,树状数组套线段树即可。
46+
47+ 但是需要稍微卡一下空间。
48+ ``` cpp
49+ // #include<bits/stdc++.h>
50+ #include < algorithm>
51+ #include < iostream>
52+ #include < cstring>
53+ #include < iomanip>
54+ #include < cstdio>
55+ #include < string>
56+ #include < vector>
57+ #include < cmath>
58+ #include < ctime>
59+ #include < deque>
60+ #include < queue>
61+ #include < stack>
62+ #include < list>
63+ using namespace std ;
64+ constexpr const int N=1e5 ,V=2e5 ;
65+ struct element {
66+ int a,b,c;
67+ }a[N+1 ];
68+ int n,k,ans[N+1 ];
69+ int size;
70+ struct node {
71+ int l,r;
72+ int lChild,rChild;
73+ int value;
74+ }t[V*80 +1 ];
75+ struct bit {
76+ struct segTree{
77+ int root;
78+ int create(node x){
79+ t[++size]=x;
80+ return size;
81+ }
82+ void up(int p){
83+ t[p].value=t[t[p].lChild].value+t[t[p].rChild].value;
84+ }
85+ void down(int p){
86+ int mid=t[p].l+t[p].r>>1;
87+ if(!t[p].lChild){
88+ t[p].lChild=create({t[p].l,mid});
89+ }
90+ if(!t[p].rChild){
91+ t[p].rChild=create({mid+1,t[p].r});
92+ }
93+ }
94+ void add(int p,int x,int k){
95+ if(t[p].l==t[p].r){
96+ t[p].value+=k;
97+ return;
98+ }
99+ int mid=t[p].l+t[p].r>>1;
100+ if(x<=mid){
101+ if(!t[p].lChild){
102+ t[p].lChild=create({t[p].l,mid});
103+ }
104+ add (t[ p] .lChild,x,k);
105+ }else{
106+ if(!t[ p] .rChild){
107+ t[ p] .rChild=create({mid+1,t[ p] .r});
108+ }
109+ add(t[ p] .rChild,x,k);
110+ }
111+ up(p);
112+ }
113+ void add(int x,int k){
114+ add(root,x,k);
115+ }
116+ int query(int p,int x){
117+ if(t[ p] .r<=x){
118+ return t[ p] .value;
119+ }
120+ // down(p);
121+ int ans=0;
122+ if(t[ p] .lChild){
123+ ans=query(t[ p] .lChild,x);
124+ }
125+ if(t[ p] .rChild){
126+ if(t[ t[ p] .rChild] .l<=x){
127+ ans+=query(t[ p] .rChild,x);
128+ }
129+ }
130+ return ans;
131+ }
132+ int query(int x){
133+ return query(root,x);
134+ }
135+ }T[ V+1] ;
136+
137+ int lowbit(int x){
138+ return x&-x;
139+ }
140+ void insert(int b,int c,int x){
141+ while(b<=k){
142+ T[ b] .add(c,x);
143+ b+=lowbit(b);
144+ }
145+ }
146+ int query(int b,int c){
147+ int ans=0;
148+ while(b){
149+ ans+=T[ b] .query(c);
150+ b-=lowbit(b);
151+ }
152+ return ans;
153+ }
154+ void build(){
155+ for(int i=1;i<=k;i++){
156+ T[ i] .root=T[ i] .create({1,k});
157+ }
158+ }
159+ }T;
160+ int main(){
161+ // freopen("test.in","r",stdin);
162+ // freopen("test.out","w",stdout);
163+
164+ ios::sync_with_stdio(false);
165+ cin.tie(0);cout.tie(0);
166+
167+ cin>>n>>k;
168+ T.build();
169+ for(int i=1;i<=n;i++){
170+ cin>>a[ i] .a>>a[ i] .b>>a[ i] .c;
171+ }
172+ sort(a+1,a+n+1,[ ] (element a,element b){
173+ if(a.a!=b.a){
174+ return a.a<b.a;
175+ }else if(a.b!=b.b){
176+ return a.b<b.b;
177+ }else{
178+ return a.c<b.c;
179+ }
180+ });
181+ for(int i=1;i<=n;i++){
182+ int cnt=1;
183+ while(i<n&&a[ i+1] .a==a[ i] .a&&a[ i+1] .b==a[ i] .b&&a[ i+1] .c==a[ i] .c){
184+ i++;
185+ cnt++;
186+ }
187+ T.insert(a[ i] .b,a[ i] .c,cnt);
188+ ans[ T.query(a[ i] .b,a[ i] .c)-1] +=cnt;
189+ }
190+ for(int i=0;i<n;i++){
191+ cout<<ans[ i] <<'\n';
192+ }
193+
194+ cout.flush();
195+
196+ /* fclose(stdin);
197+ fclose(stdout);* /
198+ return 0;
199+ }
200+ ```
0 commit comments