問題への解決策[NOIP2015]輸送計画

問題への解決策[NOIP2015]輸送計画

フェイス質問

解決

もちろん、それは各パスの長さが必要とされています。

プレフィックスとラインのルートに使用ノードが(最初は脳のポンプセグメントツリーを書きました...)

そして、明らかに貪欲の同様のアイデアがあり、

あなたの変換は、確かに最長パスの側にあります

(そうでない場合は使用はありません*)

そして、最長パスに列挙エッジを検討し、答えを計算し、それを変換し、

エッジに対して\(X- \) パスは、2つのカテゴリに分けることができる:それを通ってそれなし。

それが変換された後、その経路を通って、それは、その長さが減少しているだろう

だから、この最長経路上最も長く、

そして、それは最長のルートを取って、それは影響を受けなかったを通過しませんでした、

だから、削除\(X \)答えがあること上記2例\(最大\)

しかし、キーは、第二のケースを見つける方法である:ないの後に(xは\)\最長パスです。

列挙その後、片側かつ実現可能な表示されません求めて、

私たちは、寄付のその側経路計算を列挙考慮することができます

もちろん、パスのこちら側にこのパスを更新することができません、

だから、木の節を考えます

そのような経路は、複数のセクションに分割されます、

範囲は、更新側にその補数であります

最大セグメントツリーを維持するために、より大きな深さの点への回答に対応するエッジ。

コード(コードは非常に長くなければならないが、慎重にカンカンは理解することができます):

#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;
}

おすすめ

転載: www.cnblogs.com/zsq259/p/11828299.html
おすすめ