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<bits/stdc++.h>
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<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 1e5+5;

int n, m;
typedef pair<int,ll> P;
vector<P> 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章