線段樹 bzoj2957 樓房重建

2021-08-09 01:31:35 字數 1631 閱讀 5087

大概意思就是求序列從一位置開始的動態上公升序列。

分塊可過,但這一類題目其實可用線段樹。

也就是維護每個區間的上公升序列長度。

下面這種求法只是用於當前節點所覆蓋的區間完全被查詢區間覆蓋。

具體而言,查詢時如果左兒子的max值< k,只去右兒子找。如果max_lc>=k,那麼右兒子的長度全部符合,只要再遞迴著找左兒子即可。

因為這道題要求的區間是1~n,所以是很裸的題。。。

主體函式

int

q(double k,int x)

void up(int

x)void c(int l,double k,int

x) int mid=t[x].l+t[x].r>>1;

if(l<=mid)c(l,k,x

*2);

else c(l,k,x

*2+1);

up(x);

}

那麼,對於求給定區間的呢

其實就加了乙個地方,只要遞迴到某個節點被詢問區間完全覆蓋即可,但要按照順序列舉,並不斷更新當前的最大高度,並累加答案。

多的地方

int

q(int k,int x)

int mid=t[x].l+t[x].r>>1;

if(t[x

*2].hreturn

q(k,x*2+1);

else

return

q(k,x*2)+t[x].szr-t[x

*2].szr;

}inline void q_(int l,int r,int

x)

int mid=t[x].l+t[x].r>>1;

if(l<=mid)q_(l,r,x

*2);

if(r>mid)q_(l,r,x

*2+1);

} inline int q(int l,int k)

這道題的完整**

#include 

#include

#include

#include

#include

#define n 100005

using namespace std;

struct tree

t[n*4];

int n,m;

void build(int l,int r,int

x) int mid=l+r>>1;

build(l,mid,x

*2);

build(mid+1,r,x

*2+1);

}int

q(double k,int x)

void up(int

x)void c(int l,double k,int

x) int mid=t[x].l+t[x].r>>1;

if(l<=mid)c(l,k,x

*2);

else c(l,k,x

*2+1);

up(x);

}int main()

}

BZOJ2957 樓房重建(線段樹)

這裡放傳送門 可以發現如果一段樓房能被看見,那麼它們跟原點的連線的斜率都是單調遞增的。於是這就變成了乙個維護上公升序列的題。這裡的上公升序列不是最長上公升子串行那樣的東西,而是相當於貪心地選擇,選中的子串行中的每乙個元素它前面都不能存在大於等於它的元素。比如說,有乙個斜率序列是1,2,4,3,4,如...

BZOJ2957 樓房重建 線段樹

題目 time limit 10 sec memory limit 256 mb submit 2259 solved 1069 submit status discuss 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自...

bzoj2957樓房重建 線段樹

小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,hi 的線段表示,其中hi...