• P2680 运输计划 树链剖分


      

    在一颗有边权的树上有m条路径,清零一条边的边权使得m条路径的最大值最小。 输出这个最大值

    显然 要遍历这m条路的最长路(如果最长路有多条随意遍历一条即可) 

    因为树上距离不修改  那么用前缀和维护树上路径长度可以少一个log

    然后遍历最长路的每一条边  ans=min(ans,max(最长路的长度-这条路的长度,不经过这条边的最长路长度)

    所以现在需要维护的是不经过这条边的最长路长度

    可以遍历m  将不在这条路径上的所有边 维护一个值(就是这条路径的长度) 用线段树维护最大值即可

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=2e6+10;
    int maxx[N<<2],col[N<<2],n,m,maxans[N],d[N],maxbian,flagx,flagy,val[N];
    void build(int l,int r,int pos)
    {
        if(l==r){maxx[pos]=0;return;}
        int m=(l+r)>>1;
        build(l,m,pos<<1);build(m+1,r,pos<<1|1);
        maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]);
    }
    void down(int pos)
    {
        if(!col[pos])return ;
        col[pos<<1]=max(col[pos<<1],col[pos]);
        col[pos<<1|1]=max(col[pos<<1|1],col[pos]);
        maxx[pos<<1]=max(maxx[pos<<1],col[pos]);
        maxx[pos<<1|1]=max(maxx[pos<<1|1],col[pos]);
        col[pos]=0;
    }
    void upsum(int L,int R,int v,int l,int r,int pos)
    {
        if(L<=l&&r<=R){maxx[pos]=max(maxx[pos],v);col[pos]=max(col[pos],v);return ;}
        int m=(l+r)>>1;down(pos);
        if(L<=m)upsum(L,R,v,l,m,pos<<1);
        if(R>m)upsum(L,R,v,m+1,r,pos<<1|1);
        maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]);
    }
    void qmax(int l,int r,int pos)
    {
        if(l==r){maxans[l]=maxx[pos];return ;}
        int m=(l+r)>>1;down(pos);
        qmax(l,m,pos<<1);
        qmax(m+1,r,pos<<1|1);
    }
    int qmaxx(int x,int l,int r,int pos)
    {
        if(l==r)return maxx[pos];
        int m=(l+r)>>1;down(pos);
        if(x<=m)return qmaxx(x,l,m,pos<<1);
        else return qmaxx(x,m+1,r,pos<<1|1);
    }
    int id[N],top[N],fa[N],dep[N],son[N],siz[N],pre[N],ncnt,pos,head[N];
    struct Edge{int to,nex;}edge[N<<1];
    void add(int a,int b){edge[++pos]=Edge{b,head[a]};head[a]=pos;}
    void dfs1(int x,int f)
    {
        fa[x]=f;dep[x]=dep[f]+1;siz[x]=1;son[x]=0;
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;if(v==f)continue;
            dfs1(v,x);siz[x]+=siz[v];
            if(siz[son[x]]<siz[v])son[x]=v;
        }
    }
    void dfs2(int x,int topf)
    {
        top[x]=topf;id[x]=++ncnt;pre[ncnt]=x;
        if(son[x])dfs2(son[x],topf);
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;if(v==fa[x]||v==son[x])continue;
            dfs2(v,v);
        }
    }
    int u[N],v[N],w[N];
    int Qdis(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            ans+=d[id[x]]-d[id[top[x]]-1];
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        ans+=d[id[y]]-d[id[x]];
        return ans;
    }
    struct node
    {
        int x,y;
    }s[N];
    void UPsum(int x,int y,int v)
    {
        int cnt=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            s[++cnt].x=id[top[x]],s[cnt].y=id[x];
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        s[++cnt].x=id[x]+1,s[cnt].y=id[y];
        sort(s+1,s+1+cnt,[](node a,node b){return a.x<b.x||a.x==b.x&&a.y<b.y;});
        if(s[1].x>1)upsum(1,s[1].x-1,v,1,n,1);
        if(s[cnt].y<n)upsum(s[cnt].y+1,n,v,1,n,1);
        rep(i,1,cnt-1)
        if(s[i].y+1<=s[i+1].x-1)upsum(s[i].y+1,s[i+1].x-1,v,1,n,1);
    }
    int getans(int x,int y)
    {
        int ans=inf;
        if(x==y)return 0;
        while(x!=y)
        {
            if(dep[x]<dep[y])swap(x,y);
            ans=min(ans,max(maxbian-val[x],maxans[id[x]]));
            x=fa[x];
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        rep(i,1,n-1)
        scanf("%d%d%d",&u[i],&v[i],&w[i]),add(u[i],v[i]),add(v[i],u[i]);
        dfs1(1,1);
        dfs2(1,1);
        build(1,n,1);
        rep(i,1,n-1)
        {
            if(dep[u[i]]<dep[v[i]])swap(u[i],v[i]);
            val[u[i]]=d[id[u[i]]]=w[i];
        }
        rep(i,1,n)
        d[i]+=d[i-1];
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int temp=Qdis(x,y);
            if(temp>maxbian)maxbian=temp,flagx=x,flagy=y;
            UPsum(x,y,temp);
        }
        qmax(1,n,1);
        cout<<getans(flagx,flagy);
        return 0;
    }
    View Code
  • 相关阅读:
    Hadoop概述与配置
    组件间通讯及钩子函数
    react组件
    JSX
    Node.js二分查找
    链表
    微信支付V3
    在有序数组中查找某一特定元素的索引
    给定一个只包括 ‘(‘,‘)‘,‘{‘,‘}‘,‘[‘,‘]‘ 的字符串,判断字符串是否有效。
    我的前半生
  • 原文地址:https://www.cnblogs.com/bxd123/p/11435290.html
Copyright © 2020-2023  润新知