四维偏序 CDQ套CDQ
對CDQ深一步的理解
昨天做了一道CDQ,看了一堆CDQ可做的題,今天又做了一道四維偏序
感覺對CDQ的理解又深了一點(diǎn),故來寫一寫現(xiàn)在自己對于CDQ的理解
CDQ其實(shí)就是實(shí)現(xiàn)了這樣的一個(gè)問題的轉(zhuǎn)化:
\(a_{l} < a_{l+1} < ... < a_r => (a_l,a_{l+1},...,a_{mid}) \text{都小于} (a_{mid+1},a{mid+2},...,a_r)\)
然后我們就知道這時(shí)候左邊所有的點(diǎn)都一定小于右邊的點(diǎn)
在四維偏序的算法中,那就是左邊的點(diǎn)可以對右邊的點(diǎn)做出貢獻(xiàn)(僅在當(dāng)前維度下)
這樣就強(qiáng)行消除了一個(gè)維度的限制.
四維偏序
COGS 2479
題目大意
給定一個(gè)有\(n\)個(gè)元素的序列,元素編號為\(1~n\),每個(gè)元素有三個(gè)屬性\(a,b,c\),求序列中滿足\(i<j\)且\(a_i<a_j\)且\(b_i<b_j\)且\(c_i<c_j\)的數(shù)對\((i,j)\)的個(gè)數(shù)。
題解
我們把下標(biāo)也看作一個(gè)維度,那么這就是個(gè)四維偏序
我們在下標(biāo)的維度上CDQ
然后記錄每個(gè)元素在第一次CDQ中是較小的還是較大的.
因?yàn)橹挥休^小的元素才能對較大的元素做出貢獻(xiàn)
只有較大的元素才能接受較小的元素的影響.
所以我們處理出來后這就變成了一個(gè)三維偏序
所以我們在對這個(gè)序列(CDQ+掃描線+樹狀數(shù)組)求三維偏序即可
Code
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; inline void read(int &x){x=0;char ch;bool flag = false;while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x; } const int maxn = 50010; struct Node{int a,b,c;bool is_sm;Node(){a=b=c=is_sm = 0;} }a[maxn],tmp1[maxn],tmp2[maxn]; int c[maxn],n,init_tmp[maxn],ans=0; #define lowbit(x) (x&-x) inline void modify(int x,int y){for(;x<=n;x+=lowbit(x)) c[x] += y; } inline int query(int x){int ret = 0;for(;x;x-=lowbit(x)) ret += c[x];return ret; } void solve2(int l,int r){if(l == r) return ;int mid = l+r >> 1;solve2(l,mid);solve2(mid+1,r);int i = l,j = mid+1,k = l;Node *a = tmp1,*tmp = tmp2;init_tmp[0] = 0;while(i <= mid || j <= r){if((j > r) || (i <= mid && a[i].b < a[j].b)){if( a[i].is_sm){modify(a[i].c,1);init_tmp[++init_tmp[0]] = i;}tmp[k++] = a[i++];}else{if(!a[j].is_sm){ans += query(a[j].c);}tmp[k++] = a[j++];}}for(int i = 1;i<=init_tmp[0];++i) modify(a[init_tmp[i]].c,-1);copy(tmp+l,tmp+r+1,a+l); } void solve1(int l,int r){if(l == r) return ;int mid = l+r >> 1;solve1(l,mid);solve1(mid+1,r);int i = l,j = mid+1,k = l;Node *tmp = tmp1;while(i <= mid || j <= r){if((j > r) || (i <= mid && a[i].a < a[j].a)){(tmp[k++] = a[i++]).is_sm = true;}else (tmp[k++] = a[j++]).is_sm = false;}copy(tmp+l,tmp+r+1,a+l);solve2(l,r); } int main(){ // freopen("partial_order.in","r",stdin); // freopen("partial_order.out","w",stdout);read(n);for(int i=1;i<=n;++i) read(a[i].a);for(int i=1;i<=n;++i) read(a[i].b);for(int i=1;i<=n;++i) read(a[i].c);solve1(1,n);printf("%d\n",ans);getchar();getchar();return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/Skyminer/p/6405323.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的四维偏序 CDQ套CDQ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单一码付:将支付宝和微信的收款二维码合
- 下一篇: pdf打印机如何设置双面打印