P2680 运输计划 树链剖分

Posted bxd123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 Edgeint to,nex;edge[N<<1];
void add(int a,int b)edge[++pos]=Edgeb,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

 

以上是关于P2680 运输计划 树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

树链剖分详解

BZOJ-4326运输计划 树链剖分 + 树上差分 + 二分

[noip 2015]运输计划 [LCA][树链剖分]

树链剖分小结

树链剖分模板

NOIP 2013 火车运输Kruskal + 树链剖分