線段樹 區間合併 poj3368

2021-10-09 09:08:38 字數 2503 閱讀 8829

poj 3368 frequent values

題意:給乙個單調不遞減的數列,求給定區間內重複最多數字的次數

用線段樹進行維護的話,要記錄五個值:

區間左邊界的數字,

區間左邊界在本區間內的次數,

區間右邊界的數字 ,

區間右邊界在本區間內的次數,

該區間內出現的最大次數

在用線段樹維護的時候,不能只對左右區間的值進行比較,還要把兩個區間合併(如果 左區間的右邊界 == 右區間的左邊界)看合併後中間是否形成出現次數更多的數字

這裡引用下別的文章吧,畢竟我老懶人了(doge)

這一類區間查詢的問題很容易想到用線段樹來做。顯然我們首先要線段樹的節點中維護麼i各區間的最大次數。但這樣是不夠的,如果乙個查詢區間跨越了兩個區間,那查詢區間的最大次數怎麼取呢?取較大值?加和?顯然不是那麼簡單。

仔細觀察題目條件,陣列本身是公升序的。這表示,兩個區間連線之後,最大次數改變只可能發生在兩個區間交接的地方。即左區間的右端和右區間的左端一樣,連線起來形成了乙個比原來兩區間的最大值更大的乙個值。

而進行這個連線處的判斷和計算,我們只需要知道左子樹的右端和它在左子樹**現的次數,右子樹的左端和它在右子樹**現的次數。所以,線段樹的每個節點需要維護五個值:本區間內最大次數,左端點及其次數,右端點及其次數。

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

const

int maxn =

100000

+100

;const

int inf =

0x7f7f7f7f

;int l[maxn *4]

, l_num[maxn *4]

, r[maxn *4]

, r_num[maxn *4]

, s[maxn *4]

;//區間左邊界的數字,區間左邊界在本區間內的次數,區間右邊界的數字 , 區間右邊界在本區間內的次數

//以及該區間內出現的最大次數

int arr[maxn]

;void

update

(int rt)

//判斷是中間連同後出現次數多還是左右子樹中的出現最多次數的數字多

temp =

max(temp , s[rt<<1]

);s[rt]

=max

(temp , s[rt<<1|

1]);

//更新l[rt] 和 r[rt]

l[rt]

= l[rt<<1]

, r[rt]

= r[rt<<1|

1];//如果左兒子的左邊界和右兒子的左邊界相同,那麼該區間與左邊界相同的數字數為

//左右兒子區間左端點出現次數的和

if(l[rt<<1]

== l[rt<<1|

1])else

//右邊界數字在區間內出現次數同上

if(r[rt<<1]

== r[rt<<1|

1])else

}void

build

(int rt,

int l,

int r)

int mid =

(l + r)

>>1;

build

(rt <<

1, l , mid)

;build

(rt <<1|

1, mid +

1, r)

;update

(rt);}

intquery

(int rt ,

int l ,

int r ,

int a ,

int b)

int mid =

(l + r)

>>1;

int lr =

0, rr =0;

if(a <= mid)

if(b > mid)

//下面關於最大值要更新兩次,一次是比較左右兒子區間的最大值,還有一次是比較合併區間後

//中間數出現的次數

int res =

max(lr,rr)

;//第一次更新

//如果左右兒子出現在查詢區間內,並且左右兒子區間可以合併 ,就要考慮是否因為合併導致

//出現 出現次數更多的數字

if( lr && rr && r[rt<<1]

== l[rt<<1|

1])return res;

}int

main()

build(1

,1,n);

while

(q--)}

return0;

}

poj 3368 又一線段樹

這乙個題目是求乙個區間內重複數字的最大次數。這題有乙個特點,數字是遞增滴,相同的數字肯定是連續的。將相同的數字看做乙個部分,hash儲存每個數字屬於哪個部分。對所有的部分建一顆二叉樹,儲存此區間內最大的重複數字的個數。查詢的時候分3中情況 1 在同乙個部分,直接 尾 頭 1就是結果 2 只差乙個部分...

poj3667 線段樹(區間合併)

題意 有編號為1 n的n個房間,有兩種詢問 1.有人來訂連續的k間房,有的話返回第一間房的編號,否則返回0。2.有人退連續的從a開始的連續的k間房。1.該區間最大的連續空房數 2.該區間從最左邊起的最大的連續空房數 3.該區間從最右邊起的最大的連續空房數 根據以上三個資訊,每個非葉結點的資訊都可以由...

poj 3667 線段樹 區間合併

感想 沒有什麼說的了。越做線段樹越感覺自己水。這個我感覺自己就真坑了大家了。難的不會,簡單的也水不過了。哎,最近這是什麼情況啊!題目 題意 旅館有編號為1 n的房間,現在可能有m波人過了租房,每波人可能要定連續的d間房,如果有的話,編號盡量小,沒有的話就說0,也可能有d個人要退房,他們的房是連續的x...