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#includeusing
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 ...