• P5443 [APIO2019]桥梁 操作分块+可撤销并查集


    题意:

    戳这里

    分析:

    • 暴力
    1. 按题目模拟,对于每一个询问操作,用并查集维护满足题意的边,求查询点所在连通块大小,复杂度 (O(qmalpha))

    2. 给询问排序,按重量降序,每次把满足要求的未被修改的边加入并查集,暴力枚举合法的修改操作,可撤销并查集维护,复杂度 (O(q^2log)))

    • 正解

    两种暴力的瓶颈分别在于,一个枚举了所有的边,一个枚举了所有的操作

    那么考虑怎么均摊两个复杂度

    分块 txdy

    (block) 个操作分成一个块,对于每一个块内按照第二种暴力,对询问进行排序修改,然后处理完一个块内的询问后,把所有的修改操作加上

    这样每次查询时,枚举的被修改的边最多只有 (s) 个,所以一个块内的复杂度不超过(O(s^2alpha))

    总的复杂度不超过(O(q imes s imes alpha(块内的查询)+frac{q imes m log m}{s}(每个块的预处理)))

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        int read()
        {
            int x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const int maxn = 1e5+5;
        const int blo = 1024;
        int n,qt,cnt,top,m;
        int st[maxn],ans[maxn],fa[maxn],siz[maxn],id[maxn],vis[maxn];
    
        struct edge
        {
            int frm,to,val,id;
            bool operator <(const edge &b)const
            {
            	return val>b.val;
    		}
        }e[maxn<<1];
        
        struct query
        {
            int pos,w,tim;
            query(){}
            query(int pos,int w,int tim):pos(pos),w(w),tim(tim){}
            bool operator <(const query &b)const
            {
            	return w>b.w;
    		}
        };
        vector<query> q1,q2,tmp;
        
        int find(int x){return fa[x]==x?x:find(fa[x]);}
    
        void merge(int x,int y)
        {
            int fx=find(x),fy=find(y);
            if(fx!=fy)
            {
                if(siz[fx]<siz[fy]) swap(fx,fy);
                fa[fy]=fx;
                siz[fx]+=siz[fy];
                st[++top]=fy;
            }
        }
    
        void del(int num)
        {
            while(top>num)
            {
                int tmp=st[top--];
                siz[fa[tmp]]-=siz[tmp];
                fa[tmp]=tmp;
            }
        }
    
        void solve()
        {
            tmp.clear();top=0;
            sort(e+1,e+m+1);
            sort(q2.begin(),q2.end());
            for(int i=1;i<=m;i++) id[e[i].id]=i;//¸øÅÅÐòºóµÄ±ßÖرêºÅ 
            for(int i=1;i<=n;i++) siz[i]=1,fa[i]=i;
            
            for(auto it:q1) vis[it.pos]=-1,tmp.push_back(query(it.pos,e[id[it.pos]].val,0));//°Ñеıßtim ÉèΪ0£¬ÕâÑùÿ´Î¿ÉÒÔ½«Ö®Ç°visµÄÓ°ÏìÏûµô 
            for(auto it:q1) tmp.push_back(it);
            
            for(int i=0,it=1;i<(int)q2.size();i++)
            {
                while(it<=m&&e[it].val>=q2[i].w)
                {
                    if(!vis[e[it].id]) merge(e[it].frm,e[it].to);
                    it++;
                }
                int lst=top;
                
                for(auto x:tmp) if(x.tim<=q2[i].tim) vis[x.pos]=x.w;
                for(auto x:q1) if(vis[x.pos]>=q2[i].w) merge(e[id[x.pos]].frm,e[id[x.pos]].to);//½«·ûºÏÒªÇóµÄ±ß¼ÓÈë²¢²é¼¯ 
                
                ans[q2[i].tim]=siz[find(q2[i].pos)];
                del(lst);
            }
    		for(auto x:q1) e[id[x.pos]].val=x.w,vis[x.pos]=0;//°Ñ²Ù×÷µÄÓ°Ïì¼ÓÔØÉÏ 
    		q1.clear();q2.clear();
        }
    
        void work()
        {
            int opt;
            query x;
            n=read();m=read();
            for(int i=1;i<=m;i++)
            {
                e[i].frm=read();
                e[i].to=read();
                e[i].val=read();
                e[i].id=i;
            }
            qt=read();
            for(int i=1;i<=qt;i++)
            {
                opt=read();
                x.pos=read();x.w=read();x.tim=i;
                if(opt==1) q1.push_back(x);
                else q2.push_back(x);
                if(i%blo==0) solve();
            }
            if(qt%blo) solve();
            for(int i=1;i<=qt;i++) if(ans[i]) printf("%d
    ",ans[i]);
        }
    
    
    }
    
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    JAVA 多线程开篇 -从按顺序打印ABC开始
    学英语
    称砝码
    JAVA BST的实现
    JAVA 引用
    常用查找算法的总结
    bootstrap学习之二-组件
    bootstrap学习之一_bootstrap css
    前端学习——css实用技术
    前端学习——css基础知识,选择器与html模板、值得收藏的html标签
  • 原文地址:https://www.cnblogs.com/youth518/p/14179953.html
Copyright © 2020-2023  润新知