[BZOJ5279][Usaco2018 Open]Disruption(树剖+线段树)

版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/83186268

题目传送门

分析

  这题我们仔细分析一下,每次断掉一条树边其实就是将一棵树分成两部分,然后走一条边权最短的,端点分别在两个区域的就行了。那么转化一下题意,其实就是对于每一条树边,我们要求的就是覆盖到这条边的所有给出的m条边中边权最小的是多少。转化完之后实际上这道题就变成了链上取min然后单点查询了(将一条边边权给下放到更深的那个点的点权),然后直接上树剖+线段树就好了。复杂度 O ( n log 2 n ) O(n\log^2 n) ,据说也可以不用树剖,直接启发式合并,复杂度是 O ( n log n ) O(n\log n) 的,但我可能不太会,就写了树剖。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>inline void read(T &x) {
    x=0;T f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-48,ch=getchar();
    x*=f;
}
inline void Setfile(string Str="") {
    if(Str=="")
        return;
    freopen((Str+".in").c_str(),"r",stdin);
    freopen((Str+".out").c_str(),"w",stdout);
}
struct Edge {
    int u,v,w;
    Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
    inline bool operator < (const Edge &rhs) const {
        return w<rhs.w;
    }
};
const int maxn=100005;
vector<Edge>edges;
vector<int>G[maxn];
int n,q,fa[maxn][19],hson[maxn],sz[maxn],dfn[maxn],val[maxn],dep[maxn],clk,topx[maxn],m,fr[maxn],to[maxn],bel[maxn];
inline void dfs(int u,int fa) {
    bel[u]=1;
    for(int i=0;i<(int)G[u].size();++i) {
        int v=G[u][i];
        if(v==fa)
            continue;
        dfs(v,u);
    }
}
inline void prework(int u=1,int p=0) {
    sz[u]=1;
    for(int i=1;i<19;++i)
        fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int i=0;i<(int)G[u].size();++i) {
        int v=G[u][i];
        if(v==p)
            continue;
        dep[v]=dep[u]+1,fa[v][0]=u,prework(v,u),sz[u]+=sz[v];
        if(!hson[u]||sz[hson[u]]<sz[v])
            hson[u]=v;
    }
}
inline void fstwork(int u=1,int tp=1) {
    dfn[u]=++clk;
    topx[u]=tp;
    if(!hson[u])
        return;
    fstwork(hson[u],tp);
    for(int i=0;i<(int)G[u].size();++i) {
        int v=G[u][i];
        if(v==fa[u][0]||v==hson[u])
            continue;
        fstwork(v,v);
    }
}
namespace line {
    int tr[maxn<<2],lz[maxn<<2];
    inline void build(int o,int l,int r) {
        lz[o]=tr[o]=2e9;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(o<<1,l,mid),build(o<<1|1,mid+1,r);
    }
    inline void modify(int o,int d) {
        tr[o]=min(tr[o],d),lz[o]=min(lz[o],d);
    }
    inline void pushdown(int o) {
        if(lz[o]<2e9)
            modify(o<<1,lz[o]),modify(o<<1|1,lz[o]),lz[o]=2e9;
    }
    inline void update(int o,int l,int r,int ql,int qr,int d) {
        if(ql<=l&&r<=qr) {
            modify(o,d);
            return;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)
            update(o<<1,l,mid,ql,qr,d);
        if(qr>mid)
            update(o<<1|1,mid+1,r,ql,qr,d);
        tr[o]=min(tr[o<<1],tr[o<<1|1]);
    }
    inline int query(int o,int l,int r,int p) {
        if(l==r)
            return tr[o];
        pushdown(o);
        int mid=(l+r)>>1;
        if(p<=mid)
            return query(o<<1,l,mid,p);
        else
            return query(o<<1|1,mid+1,r,p);
    }
    inline int lca(int x,int y) {
        while(topx[x]!=topx[y]) {
            if(dep[topx[x]]>dep[topx[y]])
                x=fa[topx[x]][0];
            else
                y=fa[topx[y]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    inline void upd(int x,int y,int d) {
        while(topx[x]!=topx[y])
            update(1,1,n,dfn[topx[x]],dfn[x],d),x=fa[topx[x]][0];
        update(1,1,n,dfn[y],dfn[x],d);
    }
    inline int up(int x,int d) {
        for(int i=18;~i;--i)
            if(d>>i&1)
                x=fa[x][i];
        return x;
    }
    inline void modi(int x,int y,int d) {
        int l=lca(x,y),u=up(x,dep[x]-dep[l]-1),v=up(y,dep[y]-dep[l]-1);
        if(x!=l)
            upd(x,u,d);
        if(y!=l)
            upd(y,v,d);
    }
    inline void solve() {
        build(1,1,n);
        for(int i=0;i<m;++i)
            modi(edges[i].u,edges[i].v,edges[i].w);
        for(int i=1;i<n;++i) {
            int ans=dep[fr[i]]<dep[to[i]]?query(1,1,n,dfn[to[i]]):query(1,1,n,dfn[fr[i]]);
            printf("%d\n",ans>1e9?-1:ans);
        }
    }
}
int main() {
    Setfile();
    read(n),read(m);
    for(int i=1,x,y;i<n;++i)
        read(x),read(y),G[x].push_back(y),G[y].push_back(x),fr[i]=x,to[i]=y;
    for(int i=1,x,y,z;i<=m;++i)
        read(x),read(y),read(z),edges.push_back(Edge(x,y,z));
    prework(),fstwork();
    line::solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Effervescence/article/details/83186268