bzoj 2957 樓房重建

2022-03-27 04:32:59 字數 1255 閱讀 5532

題目

這道題真是非常巧妙了

首先分析一下對於乙個樓房\(i\)它要是想能被看見需要滿足什麼條件

顯然對於任意的\(j需要滿足

\[\frac\times j>h_j

\]也就是

\[\frac>\frac

\]也就是乙個從\(1\)開始的最長上公升子串行

那麼還有單點修改,這是乙個動態\(dp\)?

當然不是了,這裡需要乙個非常巧妙的\(pushup\)

我們設線段樹上區間\(i\)裡的最大斜率是\(mx_i\),答案是\(len_i\)

這個時候我們需要將\(ls\)和\(rs\)合併起來,非常顯然\(len_\)直接會被計入答案,而我們要考慮左區間的最大斜率對右區間的影響

那麼我們就去右區間裡找到第乙個比\(mx_\)大的斜率,統計出從這個點開始的最長上公升子串行

那麼我們就去右區間裡找,這個相當於做一次查詢,於是整體複雜度是\(o(mlog^2n)\)的

至於如何在右區間裡找,就在**裡說了,總之神仙的一批

#include#include#include#include#define re register

#define maxn 100005

#define ll long long

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

inline int read()

int n,m;

int a[maxn];

int l[maxn<<2],r[maxn<<2],len[maxn<<2];

double mx[maxn<<2];

int query(int i,double t)

void build(int x,int y,int i)

void change(int pos,double val,int i)

int mid=l[i]+r[i]>>1;

if(pos<=mid) change(pos,val,i<<1);

else change(pos,val,i<<1|1);

mx[i]=max(mx[i<<1],mx[i<<1|1]);

len[i]=len[i<<1]+query(i<<1|1,mx[i<<1]);

//左區間直接計入答案,遞迴去右區間裡找

}int main()

return 0;

}

bzoj 2957 樓房重建

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

BZOJ2957 樓房重建

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

BZOJ2957 樓房重建

題意 給定m m 100000 個操作,每次將座標軸上橫座標為x 1 x n 100000 的樓的高度設為y,之後回答在 0,0 能看到幾個樓。分析 7.19考試題,當時全場基本都寫得o nm 大暴力,gzz神犇用騙分法竟然ac了,但在bzoj上tle了,只能說考試時候資料水了。這題有兩種做法,一種...