演算法學習 整體二分

2022-03-29 06:58:00 字數 2838 閱讀 7694

我們開門見山,講講一道sb題:

給你乙個陣列,查這個陣列的第x大元素。

排序?可以

二分?怎麼做啊?

二分出乙個mid,判斷這個陣列中有多少個數小於等於mid,如果個數大於等於x,就遞迴到[l,mid]區間,否則是[mid+1,r]區間,這樣遞迴下去就能得到結果。

怎麼計算小於等於mid的個數?

for一遍原陣列?其實只要儲存陣列中值在[l,r]中的數,然後計算就好,而對於[1,l-1],可以預先儲存。

怎麼計算?樹狀陣列,範圍太大就離散化。

這樣很麻煩吧?排序更好吧?

但是當我給你多個詢問時,你就不會這麼覺得了。

回顧剛才的過程,我們做上圖的模擬。

把詢問看成球,答案的區間就是這個矩形,每一次我們將上一層的球判斷它會掉到下層的哪一塊中,掉到底層就是獲得了答案。

剛剛的過程就是球只有1個的情況。

球有多個時,就是整體二分!

就是對於當前的mid,對每乙個詢問都計算答案是大了還是小了,然後決定分配到下一層的哪邊。

要注意保證時間複雜度哦!

一道例題:hdu 5412。

查詢區間k小,要支援單點修改。

看**:

1 #include2

int n,q,a[100001],sum[300001],ans[300001],que1[300001],que2[300001],bit[300001];3

int i[300001],type[300001],ql[300001],qr[300001],k[300001

],cnt;

4 inline void ins(int t,int l,int r,int x)

5 inline void ins(int i,int x)

6 inline int qur(int i)

7void divide(int l,int r,int low,int

upp)

10int mid=low+upp>>1,cl=0,cr=0;11

for(int i_=l,i;i_<=r;++i_)

14if(type[i]==2)

15if(type[i]==3)20

}21for(int i_=l,i;i_<=r;++i_)

26for(int i=1;i<=cl;++i) i[l+i-1]=que1[i];

27for(int i=1;i<=cr;++i) i[l+cl+i-1]=que2[i];

28 divide(l,l+cl-1,low,mid); divide(l+cl,r,mid+1

,upp);29}

30int

main()

39 divide(1,cnt,1,1000000000

);40

for(int i=1;i<=cnt;++i) if(ans[i]) printf("

%d\n

",ans[i]);

41return0;

42 }

view code

一道例題:洛谷 p3332。

查詢區間k大,要支援區間加入。

看**:

1 #include 2

3 typedef long

long

ll;4

const

int mn = 50005;5

6int

n, q;78

intopt[mn], l[mn], r[mn]; ll v[mn];

9int

p[mn];

10int

s1[mn], s2[mn], t1, t2;

1112

ll sum[mn];

13int

ans[mn];

1415

ll b1[mn], b2[mn];

16 inline void add(ll *b, int i, ll x)

17 inline ll qur(ll *b, int i)

18 inline void add(int l, int

r, ll x)

23 inline ll qur(int l, int

r) 27

28void solve(int l, int r, int lb, int

rb)

35int mid = lb + rb >> 1

;36 t1 = t2 = 0;37

for (int i = l; i <= r; ++i) 45}

46else54}

55}56for (int i = l; i <= r; ++i)

61int pos =l;

62for (int i = 1; i <= t1; ++i)

63 p[pos++] =s1[i];

64for (int i = 1; i <= t2; ++i)

65 p[pos++] =s2[i];

66int m = l + t1 - 1;67

solve(l, m, lb, mid);

68 solve(m + 1, r, mid + 1

, rb);69}

7071

intmain()

77 solve(1, q, -n, n);

78for (int i = 1; i <= q; ++i)

82return0;

83 }

view code

學習 整體二分

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

演算法學習 整數二分

目前尚沒有很徹底的理解,所以先將大佬的模板和思路拷貝下來,待理解透徹後再上自己的理解。二分模板一共有兩個,分別適用於不同情況。演算法思路 假設目標值在閉區間 l,r 中,每次將區間長度縮小一半,當l r時,我們就找到了目標值。版本1當我們將區間 l,r 劃分成 l,mid 和 mid 1,r 時,其...

演算法學習 二分搜尋二分答案2

顧名思義,二分答案就是用二分查詢的思路去找答案,下面通過舉例來說明。題目 p1873 砍樹 砍下樹木的高度 h 從 0 一直到所有樹木中最高的高度 hmax 依次遞增,我們可以此為依據進行二分搜尋得出答案。includeusing namespace std long long n,m,arr 10...