概念
李超线段树可用来维护直线关系,支持:
- 加入一条直线
- 询问单点对应最优直线
结构与普通线段树类似,但更多分情况讨论
LuoguP4254 [JSOI2008]Blue Mary开公司
模板
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
#define ON_DEBUGG
#ifdef ON_DEBUGG
#define D_e_Line printf("
----------
")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "
time: %.3fms
", clock() * 1000.0 / CLOCKS_PER_SEC)
#else
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#endif
using namespace std;
struct ios{
template<typename ATP>inline ios& operator >> (ATP &x){
x = 0; int f = 1; char ch;
for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
x *= f;
return *this;
}
}io;
template<typename ATP>inline ATP Max(ATP a, ATP b){
return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
return a < 0 ? -a : a;
}
const int N = 5e5 + 7;
const int M = 5e5 + 3;
int tot;
double K[N << 1], B[N << 1];
int t[N << 2] ;
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
// y = k * x + b
double Calc(int id, int x) {
return K[id] * (x - 1) + B[id];
}
inline void Updata(int rt, int l, int r, int x) {
if(l == r){
if(Calc(x, l) > Calc(t[rt], l)) t[rt] = x;
return;
}
int mid = (l + r) >> 1;
if(K[t[rt]] < K[x]){
if(Calc(x, mid) > Calc(t[rt], mid)){
Updata(lson, t[rt]);
t[rt] = x;
}
else{
Updata(rson, x);
}
}
if(K[t[rt]] > K[x]){
if(Calc(x, mid) > Calc(t[rt], mid)){
Updata(rson, t[rt]);
t[rt] = x;
}
else{
Updata(lson, x);
}
}
}
inline double Query(int rt, int l, int r, int x) {
if(l == r) return Calc(t[rt], x);
int mid = (l + r) >> 1;
if(x <= mid){
return Max(Calc(t[rt],x), Query(lson, x));
}
else{
return Max(Calc(t[rt], x), Query(rson, x));
}
}
int main() {
int n;
io >> n;
char opt[13];
while(n--){
scanf("%s", opt + 1);
if(opt[1] == 'P'){
++tot;
scanf("%lf%lf", &B[tot], &K[tot]);
Updata(1, 1, M, tot);
}
else{
int x;
io >> x;
printf("%d
", (int)Query(1, 1, M, x) / 100);
}
}
return 0;
}
LuoguP4069 [SDOI2016]游戏
树链剖分后李超树维护
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ON_DEBUGG
#ifdef ON_DEBUGG
#define D_e_Line printf("
-----------
")
#define D_e(x) std::cerr << (#x) << " : " <<x << "
"
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <ctime>
#define TIME() fprintf(stderr, "
TIME : %.3lfms
", clock() * 1000.0 / CLOCKS_PER_SEC)
#else
#define D_e_Line ;
#define D_e(x) ;
#define FileOpen() ;
#define FilSave ;
#define Pause() ;
#define TIME() ;
#endif
struct ios {
template<typename ATP> ios& operator >> (ATP &x) {
x = 0; int f = 1; char c;
for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
x *= f;
return *this;
}
}io;
using namespace std;
template<typename ATP> inline ATP Min(ATP a, ATP b) {
return a < b ? a : b;
}
template<typename ATP> inline ATP Max(ATP a, ATP b) {
return a > b ? a : b;
}
const int N = 200007;
#define int long long
int n;
struct Edge {
int nxt, pre, w;
}e[N << 1];
int head[N], cntEdge;
inline void add(int u, int v, int w) {
e[++cntEdge] = (Edge){ head[u], v, w}, head[u] = cntEdge;
}
int dis[N], rnk[N]; // be careful
struct Line {
int K, B, val;
Line(int K = 0, int B = 123456789123456789ll, int val = 123456789123456789ll) : K(K), B(B), val(val) {}
inline int Calc(int x) {
return K * x + B;
}
}t[N << 2];
namespace ST {
int dis[N << 2], mn[N << 2];
#define ls rt << 1
#define rs rt << 1 | 1
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1,r
inline void Pushup(int &rt) {
mn[rt] = Min(mn[rt], Min(mn[ls], mn[rs]));
}
inline void Updata(int rt, int l, int r, Line x) {
int mid = (l + r) >> 1;
x.val = x.Calc(dis[mid]);
if(x.val < t[rt].val){
mn[rt] = Min(mn[rt], Min(x.Calc(dis[l]), x.Calc(dis[r])));
swap(x, t[rt]);
}
if(l == r) return;
if(x.Calc(dis[l]) >= t[rt].Calc(dis[l]) && x.Calc(dis[r]) >= t[rt].Calc(dis[r])) return;
if(x.K > t[rt].K)
Updata(lson, x);
else
Updata(rson, x);
Pushup(rt);
}
inline void Updata(int rt, int l, int r, int L, int R, Line x) {
if(L <= l && r <= R){
Updata(rt, l, r, x);
return;
}
int mid = (l + r) >> 1;
if(L <= mid) Updata(lson, L, R, x);
if(R > mid) Updata(rson, L, R, x);
Pushup(rt);
}
inline int Query(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) return mn[rt];
int minn = Min(t[rt].Calc(dis[Max(l, L)]), t[rt].Calc(dis[Min(r, R)]));
int mid = (l + r) >> 1;
if(L <= mid) minn = Min(minn, Query(lson, L, R));
if(R > mid) minn = Min(minn, Query(rson, L, R));
return minn;
}
inline void Build(int &n) {
// if(l == r){
// ST::dis[rt] = ::dis[::rnk[l]];
// mn[rt] = 123456789123456789ll;
// return;
// }
// int mid = (l + r) >> 1;
// Build(lson), Build(rson);
// Pushup(rt);
R(i,1,n) ST::dis[i] = ::dis[::rnk[i]];
nR(i,n << 2,1) mn[i] = 123456789123456789ll;
}
}
namespace TP {
int dfn[N], dfnIndex, top[N], fa[N], siz[N], son[N], dep[N];
inline void DFS_First(int u, int father) {
dep[u] = dep[father] + 1, fa[u] = father, siz[u] = 1;
for(register int i = head[u];i ; i= e[i].nxt){
int v= e[i].pre;
if(v == father) continue;
dis[v] = dis[u] + e[i].w;
DFS_First(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
inline void DFS_Second(int u, int Tp) {
top[u]= Tp, dfn[u] = ++dfnIndex, rnk[dfnIndex] = u;
if(!son[u]) return;
DFS_Second(son[u], Tp);
for(register int i = head[u]; i;i = e[i].nxt){
int v = e[i].pre;
if(v != fa[u] && v != son[u])
DFS_Second(v, v);
}
}
inline int LCA(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
inline void Updata(int x, int y, Line w) {
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
ST::Updata(1, 1, n, dfn[top[x]], dfn[x], w);
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
ST::Updata(1, 1, n, dfn[y], dfn[x], w);
}
inline int Query(int x, int y) {
int minn = 123456789123456789ll;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
minn = Min(minn, ST::Query(1, 1, n, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
return Min(minn, ST::Query(1, 1, n, dfn[y], dfn[x]));
}
}
#undef int
int main() {
#define int long long
//FileOpen();
int m;
io >> n >> m;
R(i,2,n){
int u, v, w;
io >> u >> v >> w;
add(u, v, w);
add(v, u, w);
}
TP::DFS_First(1, 0);
TP::DFS_Second(1, 1);
ST::Build(n);
while(m--){
int opt;
io >> opt;
if(opt == 1){
int u, v, a, b;
io >> u >> v >> a >> b;
int lca = TP::LCA(u, v);
TP::Updata(u, lca, (Line){-a, b + ::dis[u] * a, 0});
TP::Updata(v, lca, (Line){a, b + a * (::dis[u] - (::dis[lca] << 1)), 0});
}
else{
int u, v;
io >> u >> v;
printf("%lld
", TP::Query(u, v));
}
}
return 0;
}
没看的了,咕了