• 考试又㕛叒叕出锅了


    小迟修马路
    road.in/.out/.cpp
    【问题描述】
    ⼩小迟生活的城市是1棵树(树指的是一个含有 n 个节点以及 n-1 条边的无向连通图),节点编号从 1 到 n,每条边拥有一个权值 value,表示通过这条边的时候你需要交纳的金钱(注意,有可能这个值为负数,也就是说你经过这条边的时候你可以赚钱)小迟是一个杰出的马路工,他居住在节点 s,他能够选择任意一个节点m,并将从节点 s 到节点 m 的简单路径(简单路径指的是不经过同一个节点两次)上的所有边的权值都修改为 0.现在小迟获得 q 个请求,每个请求都是以 a b 的形式给出,表示小迟的好朋友小早希望从节点 a 走简单路径到节点 b,小迟希望能最小化小早需要缴纳的钱。
    需要注意的是,小迟获得的这 q 个请求是相互独立的,也就是说您只需要对于每一个请求,决定小迟的一个修路方案,使得小早需要缴纳的钱尽可能的少。
    【输入格式】
    输入文件名为 road.in。
    第一行三个正整数为 n,q,s。
    接下来 n-1 行,每行三个整数 x y z, 表示有一条边 (x,y),value 为 z。
    接下来 q 行,每个两个正整数 a b,表示请求。
    【输出格式】
    输出文件名为 road.out。
    Q 行,每行两个整数,表示需要缴纳的最少的钱。
    【样例输入】
    3 2 1
    1 2 1
    2 3 1
    1 2
    1 3
    【样例输出】
    0
    0
    【样例解释】
    对于第一次询问 1 2, 小迟可以修从 1 到 2 的路,从而使得小早不需要
    缴纳金钱;
    对于第二次询问 1 3, 小迟可以修从 1 到 3 的路,从而使得小早不需要
    缴纳金钱。
    【数据规模及约定】
    对于 30% 的数据,n≤1000,q≤1000.
    对于 100% 的数据,1≤n,q≤200000,1≤x,y≤n,|z|≤1000.
     
    题解:
    LCA+树剖维护最大值。这题无根,为了方便以s为根,可以算出每个点到S的dis,然后考虑清零情况,S为x y的lca,y为lca,x为lca,x y的lca在S下方
    对于第一种只能选择清左边或者清右边,对于第二三种,清到最小值就行,对于第四种与第一种类似,但是最后结果要再减去dis[lca(x,y)](考试的时候减了两倍,然后100->0)。
    这是lca部分,剩下的就需要树剖维护dis中的最大值,再用底下点的dis减去就行
     
    代码:
    #include<iostream>
    #include<cstdio>
    #define lson k<<1,l,mid
    #define rson k<<1|1,mid+1,r
    #define ls k<<1
    #define rs k<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=200005,inf=2e9;
    int n,m,cnt,s,mi,tot;
    int head[N],fa[N][23],dis[N],dep[N];
    int son[N],top[N],val[N],siz[N],id[N];
    int tr[N<<2];
    struct node{
        int to,nxt,dis;
    }e[N<<1];
    inline int read(){
        int s=0,w=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return w*s;
    }
    inline void add(int from,int to,int dis){
        e[++cnt]=(node){to,head[from],dis};
        head[from]=cnt;
    }
    void dfs(int x,int f,int di){
        dep[x]=dep[f]+1;
        fa[x][0]=f;
        dis[x]=dis[f]+di;siz[x]=1;
        for(int i=1;(1<<i)<=dep[x];++i)
            fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=e[i].nxt)
            if(e[i].to!=f){
                dfs(e[i].to,x,e[i].dis);
                siz[x]+=siz[e[i].to];
                if(siz[e[i].to]>siz[son[x]])son[x]=e[i].to;
            }
    }
    void dfs2(int x,int topf){
        top[x]=topf;id[x]=++tot;val[tot]=dis[x];
        if(!son[x])return ;
        dfs2(son[x],topf);
        int y;
        for(int i=head[x];i;i=e[i].nxt){
            y=e[i].to;
            if(y==fa[x][0]||y==son[x])continue;
            dfs2(y,y);
        }
    }
    inline int lca(int x,int y){
        if(dep[x]>dep[y])x^=y^=x^=y;
        for(int i=21;i>=0;i--)
            if(dep[x]<=dep[fa[y][i]])
                y=fa[y][i];
        if(x==y)return x;
        for(int i=21;i>=0;--i){
            if(fa[x][i]==fa[y][i])continue;
            x=fa[x][i];
            y=fa[y][i];
        }
        return fa[x][0];
    }
    inline void update(int k){
        tr[k]=max(tr[ls],tr[rs]);
    }
    void build(int k,int l,int r){
        if(l==r){
            tr[k]=val[l];
            return ;
        }
        build(lson);build(rson);
        update(k);
    }
    int ask(int k,int l,int r,int x,int y){
        if(l==x&&y==r){
            return tr[k];
        }
        if(y<=mid)return ask(lson,x,y);
        else if(x>mid)return ask(rson,x,y);
        else return max(ask(lson,x,mid),ask(rson,mid+1,y));
    }
    void query(int x,int y){
        mi=-inf;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            mi=max(ask(1,1,n,id[top[x]],id[x]),mi);
            x=fa[top[x]][0];
        }
        if(dep[x]>dep[y])swap(x,y);
        mi=max(ask(1,1,n,id[x],id[y]),mi);
    }
    int main(){
         freopen("road.in","r",stdin);
         freopen("road.out","w",stdout);
        n=read();m=read();s=read();
        int x,y,z;
        for(int i=1;i<n;++i){
            x=read();y=read();z=read();
            add(x,y,z);add(y,x,z);
        }
        dfs(s,0,0);
        dfs2(s,s);
        build(1,1,n);
        int ans;
        while(m--){
            x=read();y=read();
            z=lca(x,y);
            if(z==s){
                query(y,s);mi=dis[y]-mi;
                ans=dis[x]+(mi>0?0:mi);
                query(x,s);mi=dis[x]-mi;
                ans=min(ans,dis[y]+(mi>0?0:mi));
                printf("%d
    ",ans);
            }
            else if(z==x){
                query(y,x);mi=dis[y]-mi;
                printf("%d
    ",mi>0?0:mi);
            }
            else if(z==y){
                query(x,y);mi=dis[x]-mi;
                printf("%d
    ",mi>0?0:mi);
            }
            else {
                query(y,z);mi=dis[y]-mi;
                ans=dis[x]+(mi>0?0:mi)-dis[z];
                query(x,z);mi=dis[x]-mi;
                ans=min(ans,dis[y]+(mi>0?0:mi)-dis[z]);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    音频处理之回声消除及调试经验
    音频软件开发中的debug方法和工具
    ZJOI2015地震后的幻想乡
    HEOI2015小L的白日梦
    THUWC2017随机二分图
    PKUWC Slay The Spire
    dp的一些计划
    鸡汤征集贴
    弱菜的各种模板
    洛谷P4902乘积
  • 原文地址:https://www.cnblogs.com/sanjinliushi/p/11704800.html
Copyright © 2020-2023  润新知