题意:n条y=kx+b的直线,每次查询x处y值的最大值
代码:
#include
using namespace std;
typedef long long ll;
const int n = 50000;
struct Tree{
double k, b;
}T[(n<<2)+5];
#define mid ((l+r)>>1)
#define ls (u<<1)
#define rs (u<<1|1)
void build(int u,int l,int r){
T[u].b = -1e18, T[u].k = 0.0;
if(l == r) return;
build(ls,l,mid); build(rs,mid+1,r);
}
void change(int u,int l,int r,double K, double B){
double l1 = T[u].k*l+T[u].b, r1 = T[u].k*r+T[u].b;
double l2 = K*l+B, r2 = K*r+B;
if(l1<=l2 && r1<=r2){ T[u].k = K, T[u].b = B; return; }
if(l1>l2 && r1>r2) return;
double px = (B-T[u].b)/(T[u].k-K);
if(l2>l1){
if(px > mid) change(rs,mid+1,r,T[u].k,T[u].b), T[u].k = K, T[u].b = B;
else change(ls,l,mid,K,B);
}else{
if(px > mid) change(rs,mid+1,r,K,B);
else change(ls,l,mid,T[u].k,T[u].b), T[u].k = K, T[u].b = B;
}
}
double query(int u,int l,int r,int x){
if(l == r) return T[u].k*x+T[u].b;
if(x <= mid) return max(query(ls,l,mid,x), T[u].k*x+T[u].b);
return max(query(rs,mid+1,r,x), T[u].k*x+T[u].b);
}
int q;
int main() {
scanf("%d", &q);
char op[15]; double k, b; int x;
while(q--){
scanf("%s", op);
if(op[0] == 'P'){
scanf("%lf%lf", &b, &k);
change(1,1,n,k,b-k);
}else{
scanf("%d", &x);
printf("%lld\n", (long long)(query(1,1,n,x)/100.0));
}
}
return 0;
}
Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
int n, m;
typedef pair P;
vector G[maxn];
ll dis[maxn];
int fa[maxn], siz[maxn], son[maxn], dep[maxn];
int top[maxn], tid[maxn], rnk[maxn], tot;
int dfs1(int u, int f){
fa[u] = f, siz[u] = 1, son[u] = 0;
for(P &e:G[u]){
if(e.first == f) continue;
dis[e.first] = dis[u] + e.second;
dep[e.first] = dep[u] + 1;
siz[u] += dfs1(e.first,u);
if(siz[e.first] > siz[son[u]]) son[u] = e.first;
}
return siz[u];
}
void dfs2(int u, int tp){
top[u] = tp, tid[u] = ++tot, rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], tp);
for(P &e:G[u]){
if(e.first == fa[u] || e.first == son[u]) continue;
dfs2(e.first, e.first);
}
}
/**************/
struct Tree{
ll k, b, lx, rx, mx, MIN;
}T[maxn<<2];
#define mid ((l+r)>>1)
#define ls (u<<1)
#define rs (u<<1|1)
void build(int u, int l, int r){
T[u].k = 0ll, T[u].MIN = T[u].b = 123456789123456789ll;
T[u].lx = dis[rnk[l]], T[u].rx = dis[rnk[r]];
if(l == r) return;
T[u].mx = dis[rnk[mid]];
build(ls, l, mid); build(rs, mid+1, r);
}
void change(int u,int l,int r,int L,int R,ll k, ll b){
if(L<=l&&r<=R){
ll ly = T[u].k*T[u].lx+T[u].b, ry = T[u].k*T[u].rx+T[u].b;
ll LY = k*T[u].lx+b, RY = k*T[u].rx+b;
if(ly<=LY&&ry<=RY) return;
if(ly>=LY&&ry>=RY) { T[u].b = b, T[u].k = k, T[u].MIN = min(T[u].MIN, min(LY, RY)); return; }
double p = 1.0*(T[u].b-b)/(k-T[u].k);
if(ly<=LY){
if(p <= T[u].mx) change(ls,l,mid,L,R,T[u].k,T[u].b), T[u].k = k, T[u].b = b;
else change(rs,mid+1,r,L,R,k,b);
}else{
if(p <= T[u].mx) change(ls,l,mid,L,R,k,b);
else change(rs,mid+1,r,L,R,T[u].k,T[u].b), T[u].k = k, T[u].b = b;
}
T[u].MIN = min(T[u].MIN, min(LY, RY));
T[u].MIN = min(T[u].MIN, min(T[ls].MIN, T[rs].MIN));
return;
}
if(L <= mid) change(ls,l,mid,L,R,k,b);
if(R > mid) change(rs,mid+1,r,L,R,k,b);
T[u].MIN = min(T[u].MIN, min(T[ls].MIN, T[rs].MIN));
}
ll query(int u,int l,int r,int L,int R){
if(L<=l&&r<=R) return T[u].MIN;
ll res = min(T[u].k*dis[rnk[max(l,L)]] + T[u].b, T[u].k*dis[rnk[min(r,R)]] + T[u].b);
if(L<=mid && R>mid) return min(res, min(query(ls,l,mid,L,R), query(rs,mid+1,r,L,R)));
if(L<=mid) return min(res, query(ls,l,mid,L,R));
return min(res, query(rs,mid+1,r,L,R));
}
/***********/
inline int lca(int u, int v){
while(top[u] != top[v])
dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
return dep[u]>dep[v]?v:u;
}
void linkchange(int u, int w, ll k, ll b){
while(top[u] != top[w])
change(1,1,n,tid[top[u]],tid[u],k,b), u = fa[top[u]];
change(1,1,n,tid[w],tid[u],k,b);
}
ll linkquery(int u, int w){
ll res = 123456789123456789ll;
while(top[u] != top[w])
res = min(res, query(1,1,n,tid[top[u]],tid[u])), u = fa[top[u]];
res = min(res, query(1,1,n,tid[w],tid[u]));
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1,u,v,w; i < n; i++){
scanf("%d%d%d", &u, &v, &w);
G[u].push_back(P(v,w));
G[v].push_back(P(u,w));
}
dfs1(1,1);
dfs2(1,1);
build(1,1,n);
int op, s, t; ll k, b;
while(m--){
scanf("%d", &op);
if(op == 1){
scanf("%d%d%lld%lld",&s,&t,&k,&b);
int w = lca(s, t);
linkchange(s,w,-k,dis[s]*k+b);
linkchange(t,w,k,(dis[s]-(dis[w]<<1))*k+b);
}else{
scanf("%d%d",&s,&t);
int w = lca(s, t);
printf("%lld\n", min(linkquery(s,w), linkquery(t,w)));
}
}
return 0;
}