這是一道模板題
可以使用bitset,cdq分治,k-dtree等方式解決。
有 n個元素,第 i個元素有 ai、bi、ci三個屬性,設 f(i) 表示滿足 aj≤ai且 bj≤bi且 cj≤ci的 j 的數量。
對於 d∈[0,n),求 f(i)=d 的數量
輸入格式:
第一行兩個整數 n、k,分別表示元素數量和最大屬性值。
之後 n行,每行三個整數 ai、bi、ci
,分別表示三個屬性值。
輸出格式:
輸出 n 行,第 d+1 行表示 f(i)=d 的 i 的數量。
輸入樣例:
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
3131≤n≤100000,1≤k≤2000000101001
cdq分治,首先按對原序列進行三維排序,然後運用分治的思想,分治過程向下的時候保證a有序,分治過程回溯的時候保證b有序,某一分治中間態,我們只考慮mid左邊對mid右邊的影響(同在左邊或者同在右邊通過分治解決),因為mid左邊的a一定小於等於mid右邊的a,然後我們按照歸併排序的方法使得b也有序,這樣對於mid右邊的數來說,當前中間態有且僅有左邊的且b小於等於該數的數才能對它有貢獻,於是可以維護乙個樹狀陣列,在對b進行歸併排序的過程中,統計左邊的c出現的次數,並計算左邊的數對右邊的數的貢獻。
小細節:若兩個數的a,b,c值都相同,那麼如果直接進行cdq分治會導致相同數的貢獻不能全部計算的情況,因為cdq分治保證了每次計算左邊的數對右邊的數的貢獻,但是相同的數無論左右都對彼此有貢獻。所以要先去重,然後用乙個權值代表該數出現了多少次。
#includeusingview codenamespace
std;
const
int n = 2e5+50
;struct
ss
bool
operator == (const ss &s)const
};ss arr[n],ls[n];
pair
ls2[n];
intc[n];
void update(int pos,int
v)int sum(int
pos)
void print(int l,int
r)void cdq(int l,int r) //
分治 ;
ls[k++]=arr[i++];
}else
//右邊的數的b值比較小,那麼此時左邊的剩餘的數的b值一定都大於該數的b值,則此時對該數有貢獻的-
}while(i<=mid)
while(j<=r)
for(int i=0; i//
不能memset清空樹狀陣列
for(int i=l; i<=r; i++)arr[i]=ls[i];
//print(l,r);
}int ans[n]= ;
intmain()
else
}//for(int i=1;i<=pos;i++)printf("%d %d %d %d\n",arr[i].a,arr[i].b,arr[i].c,arr[i].value);
cdq(
1,pos);
for(int i=1; i<=pos; i++)
for(int i=0; i"
%d\n
",ans[i]);
return0;
}
三維偏序 陌上花開
有 n 個元素,每個元素有三個屬性 a i b i c i 定義 f i 為滿足 a j a i 且 b j b i 且 c j c i 的 j 的個數 ans i sum f j i 求所有的 ans i 陌上花開,心憂梓桑。cdq 分治模板題 首先以 a 為關鍵字排序,省略一維 再以 b 為關鍵...
陌上花開(三維偏序)(cdq分治)
其實就是三位偏序的模板,cdq分治入門題。學習cdq分治請看 stdcall大佬的部落格 傳送門 排序來維護第一層,cdq維護一層,樹狀陣列維護一層,然後就沒有啦qwqwq include include include include include define maxn 100010 usin...
Luogu3810 三維偏序(陌上花開)
題目背景 這是一道模板題 可以使用bitset,cdq分治,k dtree等方式解決。題目描述有 n n 個元素,第 i role presentation style position relative i i個元素有ai a i bi b i ci c i三個屬性,設f i f i 表示滿足aj...