P4254 [JSOI2008]Blue Mary开公司, P4069 [SDOI2016]游戏【李超树】

推荐博客:https://blog.csdn.net/litble/article/details/81234303

 

题目链接:https://www.luogu.org/problem/P4254

题意: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;
}

题目链接:https://www.luogu.org/problem/P4069

题目描述

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; }

 

你可能感兴趣的:(李超树)