李超線段樹可以支援如下操作:
在區間\(l~r\)加入線段\(y=kx+b\)。
詢問直線\(y=x\)與所有線段交點的\(y\)座標最值。
例題:模板題
如果該區間沒有線段或在此區間內,兩條線段沒有交點,則直接修改,不是最優的線段扔掉。
否則,在無視其它所有線段的情況下,計算出交點,並判斷哪條更優,把另一條下放到交點所在的兒子區間上。
由於每條線段最多下放\(o(logn)\)次,所以時間複雜度\(o(nlog^2n)\)。
詢問操作就是在所有包含它的區間的最優線段中找最優的。
有些類似標記永久化。
**很好寫(luogu4097):
#include #include double eps = 1e-5;
struct line
line(double k, double b, int bh)
line(int x1, int y1, int x2, int y2, int bh)
double f(int x)
};line zd[1600010];
bool bk[1600010];
double getjd(line a, line b)
bool check(line a, line b, int l, int r, int m, double x)
void pur(int i, int l, int r, line a)
double x = getjd(a, zd[i]);
if (x < l || x > r)
int m = (l + r) >> 1;
if (check(zd[i], a, l, r, m, x))
if (l < r)
zd[i] = a;
}void insert(int i, int l, int r, int l, int r, line a)
int m = (l + r) >> 1;
insert(i << 1, l, m, l, r, a);
insert((i << 1) | 1, m + 1, r, l, r, a);
}int getma(int i, int l, int r, int k, double & z) else
if (l == r) return rt;
int m = (l + r) >> 1,t;
double tz;
if (k <= m) t = getma(i << 1, l, m, k, tz);
else t = getma((i << 1) | 1, m + 1, r, k, tz);
if (tz > z || (fabs(tz - z) < eps && t < rt))
return rt;
}int ma[40010],wz[40010];
int main() else
if (x0 == x1)
}insert(1, 1, 39989, x0, x1, line(x0, y0, x1, y1, m));
} }return 0;
}
李超線段樹
首先來看一道題 heoi2013 segment 可以發現的是,實質上某個 x k 處的最大值只有乙個,因此我們需要盡可能減少計算不優的線段。那麼對於兩條線段 a,b a ne b 它們左右端點橫座標相同,就只會產生如下四種情況 從特殊情況出發,每次我們都插入一條 1,n 的線段。如果是前兩條情況,...
李超線段樹
t4正解李超線段樹?不會,滾過來學 貌似思路並不是很難的亞子 我們可以使用權值線段樹!對於每個區間,我們維護乙個最優線段 顯然對於乙個線段完全覆蓋的區間我們才處理 分四種情況討論 直接賦值 直接賦值 直接滾粗 最複雜的情況,我們考慮將覆蓋該區間最長的線段保留為最優線段 欸嘿?怎麼搞呢?其實只需判斷該...
李超線段樹
可以處理二維平面上加入線段,然後查詢單點最大值。首先我們定義乙個區間的最優勢線段,為區間中點值最大的線段,然後我們發現處理詢問,我們只需要將經過的線段樹節點上的最優勢線段對應的點值取max即可。然後考慮如何處理修改,首先將線段劃分到 o logn 個線段樹節點上。如果當前線段被最優勢線段完全覆蓋,那...