求三維偏序
設三維為a,b,c。先對a排序,這樣i的偏序就只能然而排序的時候需要三個維度都判斷一遍,最後還要去重,不然會出現實際應該記答案的數出現在它後面的情況。
(排序用的函式裡不要寫類似於<=之類的東西啊..會出奇奇怪怪的問題的(re))
然後分治來做,我們在做區間[l,r]的時候,先去做[l,m]和[m+1,r]
之後左區間[l,m],右區間[m+1,r]都已經按照b排好序了,而且左右兩區間內部的答案已經統計過了,所以現在只要考慮左區間中滿足(右區間的數)的數量就好了。
那麼就也把[l,r]按照b排好序,在排的時候再用乙個權值樹狀陣列維護c,
也就是,如果這個點是左區間的點,就把它的c值對應的樹狀陣列中+=這個點的重複數(剛才去重了)
如果這個點是右區間的點,就詢問樹狀陣列中<=它的c值的數量,然後加到這個點的答案裡。
而且每次做的時候樹狀陣列都要清空,但不能用memset來清,複雜度有問題。(一直迷信memset的速度,結果一查告訴我也就比迴圈清快一倍??)
所以只要把剛才加過的再減回去就可以了。
複雜度$o(n*log_2n*log_2k)$
也可以cdq套cdq,然後不用樹狀陣列,複雜度是一樣的。
這樣一直套下去,k維的話複雜度也就是$o(n*log^_2n)$啦
#include#include#include
#include
#include
#include
#include
#define ll long long int
#define inf 0x3f3f3f3f
#define lowbit(x) ((x)&(-(x)))
using
namespace
std;
const
int maxn=100010,maxk=200020
;ll rd()
while(c>='
0'&&c<='
9') x=x*10+c-'
0',c=getchar();
return x*neg;
}struct
nodeinp[maxn],num[maxn],tmp[maxn];
intinin,n,k;
inttr[maxk],cnt[maxn],siz[maxn],ans[maxn];
inline
bool cmp(node a,node b)
inline
void add(int x,int
y)inline
int query(int
x)void cdq(int l,int
r)else
}
while(q<=r)
for(int i=l;isiz[num[i].i]);
while(p<=m) tmp[++t]=num[p++];
memcpy(num+l,tmp+1,sizeof(node)*t);
}int
main()
sort(inp+1,inp+n+1,cmp);//
printf("ll");
for(i=1,j=0;i<=n;i++)
}n=j;
cdq(
1,n);
for(i=1;i<=n;i++) ans[cnt[i]]+=siz[i];
for(i=0;i"
%d\n
",ans[i]);
return0;
}
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...
P3810 陌上花開(CDQ分治)
題意 有n nn個元素,第i ii個元素有a ia i ai b ib i bi c ic i ci 三個屬性,設f i f i f i 表示滿足aj ai a j a i aj ai 且bj b ib j b i bj bi 且cj c ic j c i cj ci 且j ij i j i的j j...
P3810 陌上花開 CDQ分治
傳送門 有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 的數量。對於 d in 0,n 求 f i d 的數量 cdq分治模板題,我們將第一維在主函式排序後,cdq分治裡面,每...