線段樹 h poj3667 區間合併

2022-05-08 15:54:12 字數 1913 閱讀 7254

poj3667 hotel

【題目大意】

有乙個旅館,有n個房間排成一排,現在有兩種操作,第一是有x個顧客要入住連續的x個房間,

要求輸出最小的左端點的位置,不能滿足就輸出0,第二是將以l開始,長度為x的連續房間清空。

【輸入檔案】

第一行兩個數n,m,表示房間數和運算元

接下來m行,每行有兩種情況:

1 x 表示操作1

2 l x 表示操作2

【輸出檔案】

對於每乙個1操作,輸出答案。

題即為求最靠左的連續區間並置滿以及把一段區間置空。

那麼我們的線段樹正式進入了區間合併的部分

0表示沒有牛,1表示住了牛

用pre(前驅)表示該區間內的前導零個數,last(後繼,用suf比較好但當時寫了last不想改了,乙個意思),表示後導零個數,maxilen表示區間內最大連續0的個數

,tag表示該區間內全部置為tag(初值為-1)

pushup注意特殊情況,若 左/右 區間的 前驅/後繼完全覆蓋了左/右 區間,要特殊處理

if(pre[ls]==mid-l+1)pre[rt]=pre[rs]+pre[ls];

else

pre[rt]=pre[ls];

if(last[rs]==r-mid)last[rt]=last[rs]+last[ls];

else

last[rt]=last[rs];

maxilen[rt]=max (maxilen[ls] ,maxilen[rs] ,pre[rs]+last[ls] );

//最大連續區間可能在 左邊/右邊/中間(所以為什麼維護前驅後繼)

pushdown

整段操作,賦0 or 賦1

tag[ls]=tag[rs]=tag[rt];

maxilen[ls]=pre[ls]=last[ls]=!tag[rt]?(mid-l+1):0

; maxilen[rs]=pre[rs]=last[rs]=!tag[rt]?(r-mid):0

; tag[rt]=-1;

**

#include#include#include#include#include#include

using

namespace

std;

const

int n=2e6+3

;int pre[n<<2],last[n<<2],maxilen[n<<2],tag[n<<2

];int

n,m,l;

//tag -1 -> nothing 0 ; 0/1 -> get to 0/1

#define ls (rt<<1)

#define rs (ls|1)

void pushup(int rt,int l,int

r)void build(int rt,int l,int

r)void pushdown(int rt,int l,int

r)void update(int rt,int l,int r,int x,int y,int

p)pushdown(rt,l,r);

int mid=l+r>>1

;

if(x<=mid) update(ls,l,mid,x,y,p);

if(y>mid) update(rs,mid+1

,r,x,y,p);

pushup(rt,l,r);

return;}

int query(int rt,int l,int r,int

len)

intmain()

else

}return0;

}

顏色是不是很好看qwq

end

poj3667 線段樹(區間合併)

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

poj 3667 線段樹 區間合併

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

線段樹區間合併poj3667

題意 1 a表示如果有長度為a的連續的空房間,則占用 2 a b表示清空 a,a b 1 的房間 思路 線段樹區間維護,除了考慮區間上最大空房間,還要維護左邊最大連續和右邊最大連續 include include include include using namespace std define ...