zoukankan      html  css  js  c++  java
  • [2020多校联考]简单题

    Solution

    确实是简单题。边权和最小显然是最小生成树。对于一条非树边,加到树里面一定会构成一个环,那么环上的树边的边权就一定不能超过这条非树边。所以对最小生成树进行重链剖分,对于一条非树边 ((u_i,v_i)) ,对链 (u_i o v_i) 进行 (modify),维护一个最小值。而对于一条非树边要想成为树边,就至少需要把其边权修改成这条链上树边的最大值,亦可用树剖随便维护一下。复杂度 (O(mlog^2n))

    Tips

    考场上空间开小了,爆成 60。以为开够了后就过了,才发现 (m)(1e6)(n)(1e5)。虽然开的 (6) 秒,依旧过不了,只有 (90) 分。又想了想发现可以用树上差分加倍增做,但不想重构代码了,直接加了一个火车头过了。

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    #define M 1000007
    #define N 100007
    #define INF 1000000000
    #define lid id<<1
    #define rid id<<1|1
    
    inline char nc(){
        static char buf[1000000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    
    inline int read(){
        int x=0,flag=1; char c=nc();
        while(c<'0'||c>'9'){if(c=='-')flag=0;c=nc();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=nc();}
        return flag? x:-x;
    }
    
    struct Node{
        int max1,max2;
        int tag;
    }t[N<<2];
    
    struct Line{
        int x,y,dis,pos;
        inline void in(int i){x=read(),y=read(),dis=read(),pos=i;}
        bool operator <(const Line &X) const{
            return dis<X.dis;
        }
    }L[M];
    
    struct E{
        int next,to;
    }e[N<<1];
    int head[N],cnt=0,n,m,fa[N];
    int dep[N],sz[N],seg[N],top[N],in[N],son[N],D_[N];
    
    inline void add(int id,int to){
        e[++cnt]=(E){head[id],to};
        head[id]=cnt;
    }
    
    inline int find(int x){
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);
    }
    
    inline void dfs1(int u){
        sz[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u]) continue;
            fa[v]=u,dep[v]=dep[u]+1;
            dfs1(v);
            sz[u]+=sz[v];
            if(sz[v]>sz[son[u]]) son[u]=v;
        }
    }
    
    inline void dfs2(int u,int tp){
        in[u]=++cnt,top[u]=tp;
        seg[cnt]=L[D_[u]].dis;
        if(!son[u]) return ;
        dfs2(son[u],tp);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    
    inline int max(int x,int y){return x>y? x:y;}
    inline int min(int x,int y){return x<y? x:y;}
    inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
    
    inline void update(int id){
        t[id].max1=max(t[lid].max1,t[rid].max1);
        t[id].max2=max(t[lid].max2,t[rid].max2);
    }
    
    inline void build(int id,int lf,int rf){
        t[id].tag=INF;
        if(lf==rf){
            t[id].max1=seg[lf];
            t[id].max2=INF;
        }else{
            int mid=(lf+rf)>>1;
            build(lid,lf,mid);
            build(rid,mid+1,rf);
            update(id);
        }
    }
    
    inline void pushup(int id,int val){
        t[id].max2=min(t[id].max2,val);
        t[id].tag=min(t[id].tag,val);
    }
    
    inline void pushdown(int id){
        pushup(lid,t[id].tag);
        pushup(rid,t[id].tag);
        t[id].tag=INF;
    }
    
    int l,r,val;
    inline void modify(int id,int lf,int rf){
        if(l<=lf&&rf<=r)
            pushup(id,val);
        else{
            int mid=(lf+rf)>>1;
            if(t[id].tag!=INF) pushdown(id);
            if(l<=mid) modify(lid,lf,mid);
            if(r>mid) modify(rid,mid+1,rf);
            update(id);
        }
    }
    
    inline void modify_path(int u,int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            l=in[top[u]],r=in[u],modify(1,1,n);
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        l=in[u]+1,r=in[v],modify(1,1,n);
    }
    
    inline int query(int id,int lf,int rf,int op){
        if(l<=lf&&rf<=r)
            return op==1? t[id].max1:t[id].max2;
        else{
            int mid=(lf+rf)>>1,ret=0;
            if(t[id].tag!=INF) pushdown(id);
            if(l<=mid) ret=max(ret,query(lid,lf,mid,op));
            if(r>mid) ret=max(ret,query(rid,mid+1,rf,op));
            return ret;
        }
    }
    
    inline int query_path(int u,int v,int op){
        int ret=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            l=in[top[u]],r=in[u],ret=max(ret,query(1,1,n,op));
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        l=in[u]+1,r=in[v];
        return max(ret,query(1,1,n,op));
    }
    
    int ans[M];
    bool vis[M];
    int main(){
        freopen("easy.in","r",stdin);
        freopen("easy.out","w",stdout);
        n=read(),m=read();
        for(register int i=1;i<=n;i++) fa[i]=i;
        for(register int i=1;i<=m;i++) L[i].in(i);
        sort(L+1,L+1+m);
        int ret=0;
        for(register int i=1;i<=m;i++){
            int u=L[i].x,v=L[i].y;
            int fa_x=find(u),    
                fa_y=find(v);
            if(fa_x==fa_y) continue;
            fa[fa_x]=fa_y;
            add(u,v),add(v,u);
            vis[i]=1;
            if((++ret)==n-1) break;
        }
        memset(fa,0,sizeof(fa));
        cnt=0,fa[1]=1,dep[1]=1,dfs1(1);
        for(register int i=1;i<=m;i++){
            if(!vis[i]) continue;
            if(dep[L[i].x]>dep[L[i].y]) D_[L[i].x]=i;
            else D_[L[i].y]=i;
        }
        dfs2(1,1); build(1,1,n);
        for(register int i=1;i<=m;i++){
            if(vis[i]) continue;
            val=L[i].dis;
            modify_path(L[i].x,L[i].y);
            ans[L[i].pos]=query_path(L[i].x,L[i].y,1);
        }
        for(register int i=1;i<=m;i++)
            if(vis[i]) ans[L[i].pos]=query_path(L[i].x,L[i].y,2);
        for(register int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    第四章 网络层协议介绍
    第三章 交换机基本原理与配置
    网络服务综合性测试
    双向秘钥对验证
    DNS分离解析与构建智能DNS服务器
    NFS共享服务
    部署YUM仓库服务
    PXE高效能批量网络装机
    DNS综合实验
    构建DNS主 从服务器
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14044203.html
Copyright © 2011-2022 走看看