zoukankan      html  css  js  c++  java
  • bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集

    题目大意:

    给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值.
    n,q <= 50000. m <= 100000

    题解:

    通过分析可以得到,我们能经过的所有的边的两种权一定均分别不大于给定的值.
    把这些边称作可行边。那么我们把所有的可行边加入到图当中,然后判断询问的两个点是不是联通.
    如果联通我们再进一步判断一下所有与其所在的联通块联通的所有边的两种边权的分别的最大值.

    然后就是考虑如何快速统计出所有的边并将其加入到联通块中.
    我们选择如下策略: 把所有的边按第一种权排序,然后分块.
    每块内按照第二种权排序
    事实证明上面划掉的方法直接TLE
    我们考虑离线所有的操作,然后每次对第一种权在某一个块内的所有询问.
    我们知道如果某个询问的第一种权在块i中,那么1 ~ i-`中的所有边的第一种权都符合条件.
    所以这时候对1 ~ i-1块中的所有边按照第二种权排序.
    如果我们处理询问的时候按照第二种权递增访问就可以做到线性统计了.
    所以我们将所有此时应该处理的询问按照第二种权排序.
    那么我们可以线性统计所有在1 ~ i-1块中的边完成所有此时的询问.

    那么在第i个块中的呢 ?
    直接暴力查询,然后维护可持久化并查集即可.
    我们直接记录所有的操作,然后暴力撤销即可.

    不要问我复杂度是多少,O(跑的过)

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define rg register int
    inline void read(int &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 100010;
    const int maxm = 100010;
    struct Edge{
        int id;
        int u,v,a,b;
    }e[maxm],q[maxm],tmp[maxm];
    int cnt;
    inline bool cmpa(const Edge &a,const Edge &b){
        return a.a == b.a ? a.b < b.b : a.a < b.a;
    }
    inline bool cmpb(const Edge &a,const Edge &b){
        return a.b == b.b ? a.a < b.a : a.b < b.b;
    }
    int n,m;
    struct Node{
        int idx,idy,fa,siz,mxa,mxb;
        Node(){}
        Node(const int &a,const int &b,const int &c
    	 ,const int &d,const int &e,const int &f){
    	 idx = a;idy = b;fa = c;siz = d;mxa = e;mxb = f;
        }
    }sta[maxm];
    int top;
    int fa[maxn],siz[maxn],mxa[maxn],mxb[maxn];
    inline void clear(){
        for(int i=1;i<=n;++i){
    	fa[i] = i;siz[i] = 1;
    	mxa[i] = mxb[i] = -1;
        }
    }
    inline int find(int x){
        while(x != fa[x]) x = fa[x];
        return x;
    }
    inline void Union(const Edge &e){
        int x = find(e.u),y = find(e.v);
        if(siz[x] > siz[y]) swap(x,y);
        sta[++top] = Node(x,y,fa[x],siz[y],mxa[y],mxb[y]);
        mxa[y] = max(mxa[y],max(mxa[x],e.a));
        mxb[y] = max(mxb[y],max(mxb[x],e.b));
        if(x == y) return ;
        siz[y] += siz[x];fa[x] = y;
    }
    inline void Undo(){
        while(top){
    	fa[sta[top].idx] = sta[top].fa;
    	siz[sta[top].idy] = sta[top].siz;
    	mxa[sta[top].idy] = sta[top].mxa;
    	mxb[sta[top].idy] = sta[top].mxb;
    	-- top;
        }
    }
    bool ans[maxm];
    int main(){
        read(n);read(m);
        for(int i=1;i<=m;++i){
            read(e[i].u);read(e[i].v);
            read(e[i].a);read(e[i].b);
        }
        int Q;read(Q);
        for(int i=1;i<=Q;++i){
            read(q[i].u);read(q[i].v);
            read(q[i].a);read(q[i].b);
            q[i].id = i;
        }
        sort(e+1,e+m+1,cmpa);sort(q+1,q+Q+1,cmpb);
        int block = sqrt(m);
        for(int i=1;i<=m;i+=block){
            cnt = 0;
            for(int j=1;j<=Q;++j){
                if(q[j].a >= e[i].a && (i+block > m || e[i+block].a > q[j].a)){
                    tmp[++cnt] = q[j];
                }
            }
            sort(e+1,e+i,cmpb);clear();
            for(int j=1,k=1;j<=cnt;++j){
                while(k < i && e[k].b <= tmp[j].b) Union(e[k++]);
                top = 0;
                for(int l=i;l<i+block && l <= m;++l){
                    if(e[l].a <= tmp[j].a && e[l].b <= tmp[j].b) Union(e[l]);
                }
                int x = find(tmp[j].u),y = find(tmp[j].v);
                if(x == y && mxa[x] == tmp[j].a && mxb[x] == tmp[j].b) ans[tmp[j].id] = true;
                Undo();
            }
        }
        for(int i=1;i<=Q;++i) puts(ans[i] ? "Yes" : "No");
        return 0;
    }
    

    其实复杂度是:(O( msqrt{m}logm + q(logn+logq)))

  • 相关阅读:
    告别单身淘宝小店
    微信机器人 细腻化
    # 导入模块 from wxpy import * # 初始化机器人,扫码登陆 bot = Bot()
    减小文件大小 减少 帧
    无有效图视频
    生成一张白色图片的算法--逻辑
    加logo
    字幕 3系数
    音频分析 字幕同步
    尊重百度的api语音合成规则
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6667135.html
Copyright © 2011-2022 走看看