【題意】
一共有n個空位,初始全為空,會有兩種操作,一種是詢問是否有r個連續的空位,若有,則將最左端有r個連續的空位的地方全部填滿,若沒有則不填,另一種是將從u開始的d個位置全部清空
【輸入】
第一行兩個數n、m(<=50000),表示n個空位,m次操作
接下來m行每行表示一次操作,
若該行第乙個數字為1,接下來是乙個數字,表示操作一
若該行第乙個數字為2,接下來是兩個數字,表示操作二
【輸出】
對於每個操作一,若存在r個連續的空位,則輸出最靠左的r個連續空位的起點,若不存在則輸出0
解:用lsum表示當前區間最長連續字首的長度,rsum表示當前區間最長連續字尾的長度,msum表示本個區間最長連續段的長度。重點是還有乙個cover,-1表示這個區間既有非空的,又有空的; 1 表示整個當前區間都滿了; 0 表示整個區間都空了。 就是lazy。
查詢的時候,首先,得滿足有這樣連續的長度。其次:
如果當前區間字首長度就大於等於我們想要的長度的話,就返回左端點。
如果左孩子的最長長度》=wanted的話,就去左孩子裡面找。
如果包含m的連續區間》=wanted的話,就直接返回左孩子字尾的最左端。
不然,就只能去右孩子裡面找了。
做題過程:
開始沒有cover,沒有push_dn,就只有乙個push_up。 想來更新的時候不是沒有更新到底嗎,也就是說孩子還沒更新呢,所以一定得有cover的呀。
現在再一想,果然表示當前區間是線段樹的根本,我怎麼給忘了呢。。。
/*
pro: 0
sol:
date:
*/#include #include #include #include #include #include #include #include #define maxn 50010
#define lson l,m , rt << 1
#define rson m + 1, r , rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
int n,q,a,b,op;
using namespace std;
int lsum[maxn << 2], rsum[maxn << 2], msum[maxn << 2], cover[maxn << 2];
void build(int l, int r, int rt)
void push_dn(int rt, int m)
}void push_up(int rt,int m)
//int query(int dis, int l, int r, int rt)
int query(int dis, int l, int r, int rt)
void update(int l,int r, int sign, int l, int r, int rt)push_dn(rt,r - l + 1);
int m = (l + r) >> 1;
if(l <= m) update(l,r,sign,lson);
if(r > m) update(l,r,sign,rson);
push_up(rt,r - l + 1);//
}int main()
}else}}
return 0;
}
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 ...