整體二分專題

2021-09-09 01:34:17 字數 3587 閱讀 3710

何謂整體二分?

一般的二分只適用於單個詢問的,如果有很多個詢問,就變成了n

2n^2

n2或更高但整體二分則可以迅速處理多個詢問的問題

首先需要離線,讀入所有詢問

然後我們二分答案,這時候我們將詢問分成兩個部分,如果l==r就直接更新答案,否則考慮分治,詢問的答案在左邊的丟到左邊,答案在右邊的則丟到右邊,然後兩邊分別處理

整體二分的時間複雜度則為o((

n+q)

logn

logo

p)

o((n+q) logn logop)

o((n+q

)log

nlog

op)其中op是solve的過程中的一些輔助操作(如樹狀陣列)

poj2104區間第k大

靜態的區間第k大,可以主席樹,也可以整體二分,用樹狀陣列輔助查詢

code:

#include

#include

#include

#include

#include

#define lb(x) (x&-x)

using

namespace std;

inline

intread()

while

(isdigit

(ch)

)return res*f;

}const

int n=

500010

,inf=

1e9;

struct qq[n]

,q1[n]

,q2[n]

;int n,m,x,y,k,cnt,cnt1,cnt2;

int tr[n]

,ans[n]

,a[n]

;inline

void

add(

int x,

int v)

inline

intquery

(int x)

void

solve

(int l,

int r,

int l,

int r)

int mid=

(l+r)

>>

1,cnt1=

0,cnt2=0;

for(

int i=l;i<=r;i++

)else

}for

(int i=

1;i<=cnt1;i++)if

(!q1[i]

.op)

add(q1[i]

.pos,

-q1[i]

.y);

for(

int i=

1;i<=cnt1;i++

) q[l+i-1]

=q1[i]

;for

(int i=

1;i<=cnt2;i++

) q[l+cnt1+i-1]

=q2[i]

;solve

(l,mid,l,l+cnt1-1)

;solve

(mid+

1,r,l+cnt1,r);}

intmain()

;for

(int i=

1;i<=m;i++

) x=

read()

,y=read()

,k=read()

,q[++cnt]

=(q)

;solve

(-inf,inf,

1,cnt)

;for

(int i=

1;i<=m;i++

) cout<<<

'\n'

;return0;

}

hdu動態區間第k大

上面的靜態其實是把每個初始數看做一次插入操作,所以啟示我們動態的話就可以用刪除+插入操作,其餘地方相同

如果你不用整體二分,你也可以cdq,如果你不想分治,那就去寫樹套樹吧我不攔你

code:

#include

#define lb(x) (x&-x)

using

namespace std;

inline

intread()

while

(isdigit

(ch)

)return res*f;

}const

int n=

500010

,inf=

1e9;

struct qq[n]

,q1[n]

,q2[n]

;int n,m,x,y,k,cnt,cnt1,cnt2;

int tr[n]

,ans[n]

,a[n]

;inline

void

add(

int x,

int v)

inline

intquery

(int x)

void

solve

(int l,

int r,

int l,

int r)

int mid=

(l+r)

>>

1,cnt1=

0,cnt2=0;

for(

int i=l;i<=r;i++

)else

}for

(int i=

1;i<=cnt1;i++)if

(!q1[i]

.op)

add(q1[i]

.pos,

-q1[i]

.y);

for(

int i=

1;i<=cnt1;i++

) q[l+i-1]

=q1[i]

;for

(int i=

1;i<=cnt2;i++

) q[l+cnt1+i-1]

=q2[i]

;solve

(l,mid,l,l+cnt1-1)

;solve

(mid+

1,r,l+cnt1,r);}

int t[n]

;int

main()

; m=

read()

;for

(int i=

1;i<=m;i++

);q[

++cnt]

=(q)

;a[x]

=y;}

/*分為插入和刪除*/

else t[i]=1

,x=read()

,y=read()

,k=read()

,q[++cnt]

=(q);}

solve

(-inf,inf,

1,cnt)

;for

(int i=

1;i<=m;i++)if

(t[i]

) cout<<<

'\n'

;return0;

}

學習 整體二分

在?看看整體二分 整體二分是個啥,就是遞迴進行二分答案的操作,按照當前二分出的區間對詢問操作和修改操作進行左右分類。有點類似於歸併排序的樣子,但是需要用個維護區間的資料結構來維護當前詢問區間的區間的查詢和修改操作,每次查詢完當前區間的操作之後,需要清空之前的修改操作。整體二分可以保證會互相影響的操作...

整體二分總結

通常與 cdq 分治同類談論,處理的問題性質本質上有不同 整體二分,顯然整體 同時 處理多個二分查詢,通常帶有修改,我們需要分治處理 solve l,r,l,r 為操作 l,r 中答案均在 l,r 區間內 我們是分治處理 l,mid 操作的前 n 個為新增操作 靜態陣列 掃一遍操作,新增操作時把 v...

整體二分初步

整體二分是個很神的東西,它可以把許多複雜的資料結構題化簡。它的精髓在於巧妙地利用了離線的特點,把所有的修改 詢問操作整體把握。先說說第k大數吧,這種問題是整體二分的標誌性題目,什麼劃分樹啊,主席樹啊,樹套樹啊見了整體二分都得自嘆不如。首先對於一次詢問來說我們可以二分答案,然後通過驗證比答案大的數有多...