zoukankan      html  css  js  c++  java
  • CF603E Pastoral Oddities

    Link
    分析发现合法的条件为每个连通块的大小为偶数,考虑用带撤销并查集维护。
    一个暴力是从小往大加边,直到所有连通块大小都为偶数。
    线段树分治优化即可。

    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<numeric>
    #include<utility>
    #include<algorithm>
    using pi=std::pair<int,int>;
    const int N=300007;
    int n,m,top,odd,ans[N],p[N],rank[N],fa[N],size[N];pi stk[N];struct edeg{int u,v,w;}e[N];
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int find(int x){return x==fa[x]? x:find(fa[x]);}
    void merge(int u,int v)
    {
        if((u=find(u))==(v=find(v))) return ;
        if(size[u]>size[v]) std::swap(u,v);
        if(size[u]&1&&size[v]&1) odd-=2;
        fa[u]=v,size[v]+=size[u],stk[++top]={u,v};
    }
    void undo(int pos){for(int u,v;top>pos;--top)if(u=stk[top].first,v=stk[top].second,fa[u]=u,size[v]-=size[u],size[u]&1&&size[v]&1)odd+=2;}
    void solve(int l,int r,int L,int R)
    {
        if(l>r) return;
        int t=top,mid=(l+r)>>1,pos=-1;
        for(int i=l;i<=mid;++i) if(rank[i]<L) merge(e[i].u,e[i].v);
        for(int i=L;i<=R&&odd;++i)
        {
    	if(p[i]<=mid) merge(e[p[i]].u,e[p[i]].v);
    	if(!odd) {pos=i;break;}
        }
        undo(t);
        if(!~pos)
        {
    	memset(ans+l,-1,(mid-l+1)<<2);
    	for(int i=l;i<=mid;++i) if(rank[i]<L) merge(e[i].u,e[i].v);
    	return solve(mid+1,r,L,R),undo(t);
        }
        ans[mid]=e[p[pos]].w;
        for(int i=L;i<pos;++i) if(p[i]<l) merge(e[p[i]].u,e[p[i]].v);
        solve(l,mid-1,pos,R),undo(t);
        for(int i=l;i<=mid;++i) if(rank[i]<L) merge(e[i].u,e[i].v);
        solve(mid+1,r,L,pos),undo(t);
    }
    int main()
    {
        n=read(),m=read(),odd=n,std::fill(size+1,size+n+1,1),std::iota(p+1,p+m+1,1),std::iota(fa+1,fa+n+1,1);
        for(int i=1;i<=m;++i) e[i]={read(),read(),read()};
        std::sort(p+1,p+m+1,[](int i,int j){return e[i].w<e[j].w;});
        for(int i=1;i<=m;++i) rank[p[i]]=i;
        solve(1,m,1,m);
        for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    软工第三次团队作业
    软工第四次团队作业
    【alpha阶段】第一次Scrum Meeting
    Alpha阶段发布说明
    【Alpha】阶段第十次Scrum Meeting
    【Alpha】阶段第九次Scrum Meeting
    【Alpha】阶段第八次Scrum Meeting
    【Alpha】阶段第七次Scrum Meeting
    【Alpha】阶段第六次Scrum Meeting
    【Alpha】阶段第五次Scrum Meeting
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12748097.html
Copyright © 2011-2022 走看看