cdq分治學習小結

2021-08-25 11:23:54 字數 2702 閱讀 6954

一臉懵逼的學了好久,應該算學會了吧。基本了解cdq分治的思想,然而**....一如既往的醜。

cdq分治只支援離線操作,主要作用是降維,反正就是大大優化了時間和空間。(感覺不扯幾句作用非常不好)。

輸入長度為n的序列,並進行m次操作,操作分兩種

1.將編號為的數加上y(1 x y)

2.求出某區間每乙個數的和(2 x y)

典型的樹狀陣列題,但我們可以把它看做乙個二維偏序問題。這個問題一維是時間二維是每個查詢或者修改的數的位置。

因為我們是按時間順序輸入的,所以我們預設時間有序。

對於左右兩個區間合併,我們只執行左區間的修改以及右區間的查詢。

#include#includeusing namespace std;

#define n 500000+2000

int n,m,tot,ai;

int a[2*n];

struct node

q[3*n],tmp[3*n];

void cdq(int l,int r)

else

}while(i<=mid)

tmp[++ti]=q[i],i++;

while(j<=r)

for(int k=1;k<=ti;k++)

q[k+l-1]=tmp[k];

}int main()

for(int i=1;i<=m;i++)

else

}cdq(1,tot);

for(int i=1;i<=ai;i++)

printf("%d\n",a[i]);

}

有 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 131

3010

1001

典型的cdq三維分治問題,直接判斷每一維的數的大小累加答案即可。

但要注意,相同的元素取位置最往後的那個,以確保答案全部累加。

#include#include#includeusing namespace std;

#define n 100000+200

#define lowbit(x) x&(-x)

struct node

q[n],tmp[n],tmpp[n];

int n,mxt;

int f[n],ans[n],same[n],tree[2*n];

void add(int x,int ci)

int query(int x)

int cmp(node a,node b)

q[2*n],tmp[2*n],tmpp[2*n];

long long n,tot,ast,mtx;

long long tree[5*m],ans[n];

void add(long long x,long long ci)

long long query(long long x)

void cdq2(long long l,long long r)

for(long long i=l;i<=r;i++)

if((tmpp[i].vall==0&&tmpp[i].val==0)&&tmpp[i].opr==1)

add(tmpp[i].di,-1);

}void cdq1(long long l,long long r)

while(i<=mid)

tmpp[++ti]=tmp[i++],tmpp[ti].vall=0;

while(j<=r)

tmpp[++ti]=tmp[j++],tmpp[ti].vall=1;

for(long long k=l;k<=r;k++)

tmp[k]=tmpp[k];

cdq2(l,r);

}void cdq(long long l,long long r)

while(i<=mid)

tmp[++ti]=q[i++],tmp[ti].val=0;

while(j<=r)

tmp[++ti]=q[j++],tmp[ti].val=1;

for(long long k=l;k<=r;k++)

q[k]=tmp[k];

cdq1(l,r);

}int main()

else

mtx=max(mtx,x+y+d);

} cdq(1,tot);

for(long long i=1;i<=ast;i++)

printf("%lld\n",ans[i]);

}

CDQ分治學習筆記

今天學了一下cdq分治,感覺這東西真的挺好用的,趕緊寫點東西怕以後再忘咯 其實類似於cdq分治的東西在oi早期學排序的時候就應該學過,那就是歸併排序 歸併排序的原理和cdq分治大體一樣,先劃分成兩個區間,遞迴解決兩邊,再合併起來 並且用歸併排序求逆序對的時候本質上就是在解決乙個二維偏序的問題 首先回...

CDQ分治 學習筆記

對於每個 查詢 操作,其結果ans i 1,i 1 ans i 1,i 1 ans i 1,i 1 中所有修改對其造成影響的疊加 這裡的 疊加 需要能夠比較方便的維護,例如sum min max sum min max sum mi n ma x等 定義s ol ve l r solve l,r s...

cdq分治學習筆記

0xff 學習cdq分治的前置知識 分治 歸併排序 分治 分治,字面上的解釋是 分而治之 就是把乙個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題 直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。度娘 歸併排序 歸併排序是普通分治的一種基本應用。將排序序列分...