ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[2020多校联考]简单题

2020-11-26 20:05:01  阅读:130  来源: 互联网

标签:int top 多校 ret 联考 tag 2020 inline id


Solution

确实是简单题。边权和最小显然是最小生成树。对于一条非树边,加到树里面一定会构成一个环,那么环上的树边的边权就一定不能超过这条非树边。所以对最小生成树进行重链剖分,对于一条非树边 \((u_i,v_i)\) ,对链 \(u_i\to v_i\) 进行 \(modify\),维护一个最小值。而对于一条非树边要想成为树边,就至少需要把其边权修改成这条链上树边的最大值,亦可用树剖随便维护一下。复杂度 \(O(m\log^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\n",ans[i]);
}

标签:int,top,多校,ret,联考,tag,2020,inline,id
来源: https://www.cnblogs.com/wwlwQWQ/p/14044203.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有