zoukankan      html  css  js  c++  java
  • [树链剖分]JZOJ 5914 盟主的忧虑

    Description

        江湖由 N 个门派(2≤N≤100,000,编号从 1 到 N)组成,这些门派之间有 N-1 条小道将他们连接起来,每条道路都以“尺”为单位去计量,武林盟主发现任何两个门派都能够直接或者间接通过小道连接。
        虽然整个江湖是可以互相到达的,但是他担心有心怀不轨之徒破坏这个武林的安定,破坏小道,于是武林盟主又秘密地修建了 M 条密道(1≤M≤100,000),但每条小道距离都不超过10亿尺。
        果不其然,最近一个名叫“太吾”的组织意欲破坏武林的小道,请你帮盟主想想办法,如果门派 A 到门派 B 的直连小道被破坏,从 A 走到 B 的所有路径中,经过密道的距离最少是多少? 
     
     

    Input

    第一行数字 N M
    接下来 N-1 行,每行两个整数 A B,表示 A-B 间有一条直连小道
    接下来 M 行,每行三个数字 A B V,表示 A-B 间有一条代价为 V 的密道

    Output

     输出 N-1 行,对应原输入的小道,每个小道被破坏后,最少需要经过多长的密道?如果不存在替换的道路,请输出-1
     
     

    Sample Input

    6 3
    4 1
    1 3
    4 5
    1 2
    6 5
    3 6 8
    2 3 7
    6 4 5

    Sample Output

    8
    7
    5
    7
    5
     

    Data Constraint

    30%数据:N<=300,M<=1000
    50%数据:N<=1000,M<=1000
    70%数据:N<=5000,M<=5000
    对于另外15%的数据点:树是一条链
    100%数据:N,M<=100,000

    分析

    这题显然密道会密道两端到LCA中经过的边的值

    这不就是树链剖分嘛

    写个区间修改走人

    什么?并查集做法?不会

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define rep(i,a,b) for (i=a;i<=b;i++)
    using namespace std;
    const int N=1e5+10;
    struct Node {
        int sz,f,s,seg,top,dep;
    }a[N];
    int scnt,rev[N];
    struct Edge {
        int u,v,nx;
    }g[2*N];
    int cnt,list[N];
    int t[4*N],lz[4*N];
    int mn;
    int n,m;
    
    void Add(int u,int v) {g[++cnt].u=u;g[cnt].v=v;g[cnt].nx=list[u];list[u]=cnt;}
    
    void Dfs1(int x,int f) {
        a[x].f=f;a[x].dep=a[f].dep+1;a[x].sz=1;
        for (int i=list[x];i;i=g[i].nx)
        if (g[i].v!=f) {
           Dfs1(g[i].v,x);
           a[x].sz+=a[g[i].v].sz;
            if (a[g[i].v].sz>a[a[x].s].sz) a[x].s=g[i].v;
        }
    }
    
    void Dfs2(int x,int f) {
        int son=a[x].s;
        if (son) {
            a[son].seg=++scnt;
            rev[scnt]=son;
            a[son].top=a[x].top;
            Dfs2(son,x);
        }
        for (int i=list[x];i;i=g[i].nx)
        if (!a[g[i].v].top) {
            a[g[i].v].seg=++scnt;
            rev[scnt]=g[i].v;
            a[g[i].v].top=g[i].v;
            Dfs2(g[i].v,x);
        }
    }
    
    void Build(int x,int l,int r) {
        if (l==r) {
            t[x]=2147483647;
            return;
        }
        int mid=l+r>>1;
        Build(x<<1,l,mid);Build((x<<1)+1,mid+1,r);
        t[x]=2147483647;
    }
    
    void Pushdown(int x) {
        if (lz[x]) {
            t[x<<1]=lz[x<<1]=min(!lz[x<<1]?2147483647:lz[x<<1],lz[x]);
            t[(x<<1)+1]=lz[(x<<1)+1]=min(!lz[(x<<1)+1]?2147483647:lz[(x<<1)+1],lz[x]);
            lz[x]=0;
        }
    }
    
    void Change_In_Segment(int x,int l,int r,int val,int ll,int rr) {
        if (ll>rr) return;
        if (l>rr||ll>r) return;
        if (ll<=l&&r<=rr) {
            t[x]=min(t[x],val);
            lz[x]=min(!lz[x]?2147483647:lz[x],val);
            return;
        }
        Pushdown(x);
        int mid=l+r>>1;
        if (mid>=ll) Change_In_Segment(x<<1,l,mid,val,ll,rr);
        if (mid<rr) Change_In_Segment((x<<1)+1,mid+1,r,val,ll,rr);
        t[x]=min(t[x<<1],t[(x<<1)+1]);
    }
    
    void Query_In_Segment(int x,int l,int r,int ll,int rr) {
        if (ll>rr) return;
        if (r<ll||l>rr) return;
        if (ll<=l&&r<=rr) {
            mn=min(mn,t[x]);
            return;
        }
        Pushdown(x);
        int mid=l+r>>1;
        if (ll<=mid) Query_In_Segment(x<<1,l,mid,ll,rr);
        if (mid+1<=rr) Query_In_Segment((x<<1)+1,mid+1,r,ll,rr);
    }
    
    void Query_In_Tree(int x,int y) {
        int fx=a[x].top,fy=a[y].top;
        while (fx!=fy) {
            if (a[fx].dep<a[fy].dep) swap(x,y),swap(fx,fy);
            Query_In_Segment(1,1,scnt,a[fx].seg,a[x].seg);
            x=a[fx].f;fx=a[x].top;
        }
        if (a[x].dep>a[y].dep) swap(x,y);
        Query_In_Segment(1,1,scnt,a[x].seg+1,a[y].seg);
    }
    
    void Change_In_Tree(int x,int y,int val) {
        int fx=a[x].top,fy=a[y].top;
        while (fx!=fy) {
            if (a[fx].dep<a[fy].dep) swap(x,y),swap(fx,fy);
            Change_In_Segment(1,1,scnt,val,a[fx].seg,a[x].seg);
            x=a[fx].f;fx=a[x].top;
        }
        if (a[x].dep>a[y].dep) swap(x,y);
        Change_In_Segment(1,1,scnt,val,a[x].seg+1,a[y].seg);
    }
    
    int main() {
        freopen("worry.in","r",stdin);
        freopen("worry.out","w",stdout);
        int i;
        char s[20];
        scanf("%d%d",&n,&m);
        rep(i,1,n-1) {
            int u,v;
            scanf("%d%d",&u,&v);
            Add(u,v);Add(v,u);
        }
        Dfs1(1,0);
        scnt=1;
        a[1].seg=a[1].top=rev[1]=1;
        Dfs2(1,0);
        Build(1,1,scnt);
        for (int i=1;i<=m;i++) {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            Change_In_Tree(x,y,w);
        }
        for (int i=1;i<=n-1;i++) {
            mn=2147483647;
            Query_In_Tree(g[i*2-1].u,g[i*2-1].v);
            printf("%d
    ",mn==2147483647?-1:mn);
        }
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    第一节:SpringMVC概述
    SpringMVC【目录】
    Windows 系统快速查看文件MD5
    (error) ERR wrong number of arguments for 'hmset' command
    hive使用遇到的问题 cannot recognize input
    Overleaf支持的部分中文字体预览
    Understanding and Improving Fast Adversarial Training
    Django2实战示例 第十三章 上线
    Django2实战示例 第十二章 创建API
    Django2实战示例 第十一章 渲染和缓存课程内容
  • 原文地址:https://www.cnblogs.com/mastervan/p/9818585.html
Copyright © 2011-2022 走看看