Solution to a problem [NOIP2015] transport plan

Solution to a problem [NOIP2015] transport plan

Face questions

Resolve

Of course, it is the length of each path is required.

The use node to the root of the prefix and the line (initially wrote a brain pumping segment tree ...)

Then obviously there is a similar idea of ​​greedy,

Your transformation is certainly on the side of the longest path,

(Otherwise there is no use *)

Then consider enumeration edge on the longest path, transform it to calculate the answer,

For edge \ (the X-\) , the path can be divided into two categories: through it and without it.

After it has been transformed, through its path it will have reduced its length,

So is the longest on this longest path,

And it did not go through it was not affected, taking the longest route,

So delete \ (x \) answer is that the above two cases \ (max \) ,

But the key is how to find the second case: not after \ (x \) is the longest path.

Enumeration one side and then seek not appear feasible,

We can consider enumerate its side path computation of contributions,

Obviously not on this side of the path can be updated this path,

So consider a tree section,

Such a path would be divided into multiple sections,

The range is its complement to update side,

Edge corresponding to the answers to a larger depth point, to maintain a maximum segment tree.

code (the code should be quite long but carefully Kankan can understand):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fot for
#define ls(a) a<<1
#define rs(a) a<<1|1
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std;

inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    return f*sum;
}

const int N=3000005;
struct ques{int s,t,w;}q[N];
struct edge{int to,next,w;}e[N<<1];
struct tree{int l,r,sum,maxn,tag;}t[N<<1];
struct qujian{int l,r;}sta[N];
struct node{int size,son,id,fa,dep,top,val;}a[N];
int n,m,tot,pla[N],ans;
int head[N],cnt,s[N];

inline void add(int x,int y,int w){
    e[++cnt]=(edge){head[x],y,w};head[x]=cnt;
}

inline void dfs1(int x,int fa){
    a[x].size=1;a[x].fa=fa;
    a[x].dep=a[fa].dep+1;
    for(int i=head[x];i;i=e[i].to){
        int k=e[i].next;        
        if(k==fa) continue;
        s[k]=s[x]+e[i].w;
        dfs1(k,x);a[k].val=e[i].w;
        a[x].size+=a[k].size;
        if(a[k].size>a[a[x].son].size) a[x].son=k;
    }
}

inline void dfs2(int x,int top){
    a[x].top=top;a[x].id=++tot;
    pla[tot]=x;
    if(a[x].son) dfs2(a[x].son,top);
    for(int i=head[x];i;i=e[i].to){
        int k=e[i].next;
        if(k==a[x].fa||k==a[x].son) continue;
        dfs2(k,k);
    }
}

inline void build(int p,int l,int r){
    t[p].l=l;t[p].r=r;
    if(l==r) {t[p].sum=a[pla[l]].val;return ;}
    int mid=(l+r)>>1;
    build(ls(p),l,mid);build(rs(p),mid+1,r);
}

inline int lca(int x,int y){
    while(a[x].top!=a[y].top){
        if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
        x=a[a[x].top].fa;
    }
    if(a[x].dep>a[y].dep) swap(x,y);
    return x;
}

inline int dis(int x,int y){
    return s[x]+s[y]-2*s[lca(x,y)];
}

inline bool cmp(ques a,ques b){return a.w>b.w;}

inline void Pushup(int p){
    t[p].maxn=max(t[ls(p)].maxn,t[rs(p)].maxn);
}

inline void Pushdown(int p){
    int ret=t[p].tag;
    t[ls(p)].tag=max(t[ls(p)].tag,ret);
    t[rs(p)].tag=max(t[rs(p)].tag,ret);
    t[ls(p)].maxn=max(t[ls(p)].maxn,ret);
    t[rs(p)].maxn=max(t[rs(p)].maxn,ret);
}

inline void change(int p,int l,int r,int w){
    if(l>r||!l||!r) return ;
    if(t[p].l>=l&&t[p].r<=r){
        t[p].maxn=max(t[p].maxn,w);
        t[p].tag=max(t[p].tag,w);
        return ;
    }
    Pushdown(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid) change(ls(p),l,r,w);
    if(r>mid) change(rs(p),l,r,w);
    Pushup(p);
}

inline bool cmp1(qujian a,qujian b){return a.l<b.l;}

inline void find(int x,int y,int w){
    int top=0;
    while(a[x].top!=a[y].top){
        if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
        sta[++top]=(qujian){a[a[x].top].id,a[x].id};
        x=a[a[x].top].fa;
    }
    if(a[x].dep>a[y].dep) swap(x,y);
    sta[++top]=(qujian){a[x].id+1,a[y].id};
    int L=1,R;
    sort(sta+1,sta+top+1,cmp1);
    for(int i=1;i<=top;i++){
        R=sta[i].l-1;
        change(1,L,R,w);
        L=sta[i].r+1;
    }
    change(1,L,n,w);
}

inline int search(int p,int x){
    if(t[p].l==t[p].r) return t[p].maxn;
    Pushdown(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(x<=mid) return search(ls(p),x);
    else return search(rs(p),x);
}

inline void solve(int x,int y){
    int pp=lca(x,y);
    while(x!=pp){
        ans=min(ans,max(q[1].w-a[x].val,search(1,a[x].id)));
        x=a[x].fa;
    }
    while(y!=pp){
        ans=min(ans,max(q[1].w-a[y].val,search(1,a[y].id)));
        y=a[y].fa;      
    }
}

signed main(){
    n=read();m=read();  
    for(int i=1;i<n;i++){
        int x=read(),y=read(),w=read();
        add(x,y,w);add(y,x,w);
    }
    for(int i=1;i<=m;i++){
        q[i].s=read(),q[i].t=read();
    }
    dfs1(1,0);dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        q[i].w=dis(q[i].s,q[i].t);
    }
    for(int i=1;i<=m;i++) find(q[i].s,q[i].t,q[i].w);
    sort(q+1,q+m+1,cmp);
    ans=q[1].w;
    fot(int i=1;i<=m;i++)
        if(q[i].w==q[1].w) solve(q[i].s,q[i].t);
        else break;
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/zsq259/p/11828299.html
Recommended