一般情況下,我們比較乙個數大小,就是ai>aj即可,
而在上公升子串行中,當i>j並且ai>aj的時候,才可以認為i這位的數大於j這位的數。
這就是乙個二維偏序。
類似的,有n個數,每個數m個屬性,乙個數比另乙個數大,當且僅當這個數的所有屬性都大於另乙個數。
這就是乙個m維偏序。
對於三維偏序,可以用cdq分治、排序、樹狀陣列處理。
有 n 個元素,第 i 個元素有 ai、bi、ci三個屬性,設 f(i)表示滿足 aj≤ai且bj≤bi且cj≤ci的 j的數量。
對於d∈[0,n) ,求 f(i) = d的數量
三維偏序的模板題。
我們先按照a從小到大排序,
然後cdq分治。
先遞迴到兩邊,
回溯到這一層之後,把左兒子的所有的數按照b排序,右兒子的所有數也按照b排序。
這樣,左兒子的數之間雖然a不一定遞增,但是因為開始按照a排序,所以左邊所有的數的a一定都小於右邊的數。
b排好序之後,
兩個指標j,i分別從1~mid,mid+1~r 即左右兒子區間的起止點開始走,,
對於右邊的乙個數i,當j的數的b值不大於i的b值時,不斷向後走j,並且把這些數的c值放進乙個權值樹狀陣列裡,
當j的b值大於i之後,當前所有左兒子裡面,b小於i這個數的數的c屬性都放進樹狀陣列裡了。
只有放進去的這些數才可能來更新f值。
在i向後走之前,f[a[i].ans]+=query(a[i].z),滿足第三個條件的數也找到了。
就把所有當前這個層裡面,符合條件的數都找出來了。
最後,把樹狀陣列加上的 1都消去。
由於cdq分治,會把i之前的所有的數都分成logn個區間,更新完f[i]了。
大家可以手動畫圖,或者模擬一下。
複雜度:nlogn^2
那麼,這個演算法是怎麼樣實現三維偏序的處理呢?
1.對於a,開始直接排序,並且,每次是先遞迴左右兒子,再處理這一層,
所以保證乙個數pi前面的所有的數,不論之後怎麼換位置,都不會到i的後面。
這就利用位置保證了所有可能更新f[i]的數對於a都是合法的。
2.對於b,我們每次回溯的時候,按照b排了乙個序,
對於左子區間對右子區間的影響,通過指標,把b小於等於i的數的所有數的c放進了樹狀陣列裡。
這樣,i前面的logn個區間,會把所有b小於i的b的數都考慮一遍的。也合法。
3.對於c,直接通過樹狀陣列字首和,一步就求出來了當前合法的所有數了。
相當於乙個篩,留下a合法的,留下b合法的,最後能被c留下的,就是所有合法的了。
注意因為是小於等於號,所以我們先把所有的完全相同的數合併成乙個數,統計的時候,乙個數也大於等於自己。再加上就好了。
就是細節問題。
#includeusing三維偏序namespace
std;
const
int n=100000+10
;int
n,m;
intf[n];
struct
nodea[n],b[n];
intpp;
bool
cmpx(node p,node q)
return p.x
}bool
cmpy(node p,node q)
return p.y
}struct
ta
int ask(int
x)}t;
void cdq(int l,int
r) a[i].ans+=t.ask(a[i].z);
}for(i=l;i)
}int
ans[n];
intmain()
sort(b+1,b+m+1
,cmpx);
int c=0
;
for(int i=1;i<=m;i++)
}cdq(
1,n);
for(int i=1;i<=n;i++)
for(int i=0;i)
return0;
}
要是維數再多了呢??
給出n個人的5個科目分數,給出q個詢問~~,每次給你5個科目的具體分數。求一共有多少個人對應的5個科目都小於等於你的科目分數~~
n,q<=50000
這就是5維偏序了。
顯然cdq分治不容易解決了。難以巧妙處理5維。
就考慮比較暴力的思路:
把成績5種分成5組,每一組從小到大按成績排序。
每次二分出id,id的成績恰好位於成績查詢邊界。
這樣可以知道該成績是有幾個人不滿足。
但是,由於有5個,所以必須知道都是誰。。。。
用乙個bitset<50001>s[5][50000]表示,第i維,前j個人滿足不合格的情況下,都是誰(s[i][j][k]=1表示,i維,編號是k的人,成績比倒數第j名可能還差。)
然後預處理出bitset(每次j加一,就把j+1的人或進去就行了),查詢的時候,二分id,之後取出這5個bitset,&一下就知道最後剩誰了,統計1的個數。
但是bitset還是太大了,不是mle,就是tle。
所以,考慮分塊!??!
bitset<50001>s[5][250]表示,第i維,前j塊不合格,都是誰
預處理比較容易,乙個塊乙個塊內暴力處理,最後從前到後相鄰的塊乙個字首或就可以了
查詢的時候,
二分出來乙個id,在塊k裡,
就找到k,把k-1塊的不合格人都找出來,之後剩下的暴力加進去就可以啦
複雜度:o(5 * q * sqrtn)(不算預處理)
因為這個是n<=50000,所以分塊卡不掉。
這種資料範圍,多維偏序都可以類似擴充套件開來。
本質上還是乙個篩。不過用了bitset和分塊優化。
總結:感覺多維偏序在生活中還是比較常見的,
比方說,你期末考試之後,想看看完虐多少個人?(每一科都比ta高)
就是多維偏序了。
bitset做多維偏序
很久以前就聽說這個大名鼎鼎的東西 暴力 了,現在才去寫。其實很簡單,對每一維排序,從左到右掃,維護乙個bitset表示這位之前的某個點是否出現 即出現則該位為1否則0 查詢某個數時則在每一維的排序完陣列二分找到最右邊 這個數這一維權值的位置,取出該位的bitset,將每一維的bitset與起來即可得...
等價,偏序和全序
等價 設 r 是某個集合 a 上的乙個二元關係。若 r 滿足以下條件 自反性 對稱性 傳遞性 則稱 r 是乙個定義在 a 上的等價關係。習慣上會把等價關係的符號由 r 改寫為 例如,設 上的關係r 如下 其中 與 y模 3 同餘,即 x 除以 3 的餘數與 y 除以 3 的餘數相等。例子有 1r4,...
貪心 偏序 treap
貪心 偏序 treap c.booking system 題意 乙個餐館,n批顧客,每批顧客都想要坐在同一張桌子上,人數為c,將付的錢是p,m張桌子,有容量desk c,得到最多的錢,輸出兩兩配對結果 題解 貪心,有兩種貪心策略 1.讓桌子選,根據容量從小到大依次選,選可以滿足要人數求中錢最多的 2...