4515: [Sdoi2016]游戏

4515: [Sdoi2016]游戏

链接

分析:

  树链剖分 + 超哥线段树。注意细节。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define Root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 100005;
const LL INF = 123456789123456789ll;
struct Edge{ int to, nxt, w; } e[N << 1];
int head[N], dep[N], siz[N], fa[N], son[N], dfn[N], bel[N], n, En, Index;
LL dis[N];
struct Line{
    LL k, b;
    Line() { k = 0, b = INF; } 
    Line(LL _k,LL _b) { k = _k, b = _b; }
    LL f(LL x) { return x * k + b; }
};

inline void add_edge(int u,int v,int w) {
    ++En; e[En].to = v, e[En].w = w, e[En].nxt = head[u]; head[u] = En;
    ++En; e[En].to = u, e[En].w = w, e[En].nxt = head[v]; head[v] = En;
}

struct SegmentTree{
    LL ans[N << 2], A[N]; Line T[N << 2];
    void init() {
        for (int i = 0; i <= (N << 2); ++i) ans[i] = INF;
    }
    inline void pushup(int rt) { ans[rt] = min(ans[rt], min(ans[rt << 1], ans[rt << 1 | 1])); }
    void Cover(int l,int r,int rt,Line v) {
        int mid = (l + r) >> 1;
        if (v.f(A[mid]) < T[rt].f(A[mid])) ans[rt] = min(ans[rt], min(v.f(A[l]), v.f(A[r]))), swap(v, T[rt]); // A[l]!!!
        if (l == r) return ;
        if (v.f(A[l]) > T[rt].f(A[l]) && v.f(A[r]) > T[rt].f(A[r])) return ;
        if (v.k > T[rt].k) Cover(lson, v);
        else Cover(rson, v);
        pushup(rt);
    }
    void update(int l,int r,int rt,int L,int R,Line v) {
        if (L <= l && r <= R) { Cover(l, r, rt, v); return ; }
        int mid = (l + r) >> 1;
        if (L <= mid) update(lson, L, R, v);
        if (R > mid) update(rson, L, R, v);
        pushup(rt);
    }
    LL query(int l,int r,int rt,int L,int R) {
        if (L <= l && r <= R) return ans[rt]; // L <= r !!!
        int mid = (l + r) >> 1;
        LL res = min(T[rt].f(A[max(l, L)]), T[rt].f(A[min(r, R)]));
        if (L <= mid) res = min(res, query(lson, L, R));
        if (R > mid) res = min(res, query(rson, L, R));
        return res;
    }
}T;
void dfs1(int u) {
    dep[u] = dep[fa[u]] + 1;
    siz[u] = 1;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa[u]) continue;
        fa[v] = u;
        dis[v] = dis[u] + e[i].w;
        dfs1(v);
        siz[u] += siz[v];
        if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;    
    }
}
void dfs2(int u,int top) {
    bel[u] = top;
    dfn[u] = ++Index; T.A[Index] = dis[u];
    if (!son[u]) return ;
    dfs2(son[u], top);
    for (int i = head[u]; i; i = e[i].nxt) 
        if (e[i].to != fa[u] && e[i].to != son[u]) dfs2(e[i].to, e[i].to);
}
int LCA(int u,int v) {
    while (bel[u] != bel[v]) dep[bel[u]] > dep[bel[v]] ? u = fa[bel[u]] : v = fa[bel[v]];
    return dep[u] < dep[v] ? u : v;
}
void Change(int u,int w,Line x) {
    while (bel[u] != bel[w]) 
    T.update(Root, dfn[bel[u]], dfn[u], x), u = fa[bel[u]];
    T.update(Root, dfn[w], dfn[u], x);
}
void Query() {
    int u = read(), v = read(); LL res = INF;
    while (bel[u] != bel[v]) {
        if (dep[bel[u]] < dep[bel[v]]) swap(u, v);
        res = min(res, T.query(Root, dfn[bel[u]], dfn[u]));
        u = fa[bel[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    res = min(res, T.query(Root, dfn[v], dfn[u]));
    printf("%lld\n", res);
}
int main() {
    n = read();int m = read();
    for (int i = 1; i < n; ++i) {
        int u = read(), v = read(), w = read();
        add_edge(u, v, w);
    }
    dfs1(1); dfs2(1, 1); T.init();
    while (m --) {
        int opt = read();
        if (opt == 1) {
            int u = read(), v = read(), w = LCA(u, v);LL a = read(), b = read();
            Change(u, w, Line(-a, b + dis[u] * a));
            Change(v, w, Line(a, b + a * (dis[u] - (dis[w] << 1))));
        }
        else Query();
    }
    return 0;
}

 

上一篇:1797: [Ahoi2009]Mincut 最小割


下一篇:VS2003"无法启动调试 没有正确安装调试器"的解决方法