• BZOJ4537 : [Hnoi2016]最小公倍数


    将边按$a$从小到大排序,每$sqrt{m}$个取一个关键点。

    对于每个关键点,将这个点之前的边以及要在这个关键点回答的询问按$b$排序。

    依次加入这个关键点之前的每条边,用并查集维护每个连通块$a$和$b$的最大值。

    对于零碎部分,只有$sqrt{m}$条边,暴力加入即可。

    用一个栈按时间记录所有修改操作,然后撤销操作即可。

    时间复杂度$O(msqrt{m}log n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=50010,M=100010;
    int n,m,Q,lim,i,j,k,o,x,y,ans[N],cnt,a[M],b[N];
    int f[N],d[N],va[N],vb[N],co;
    struct P{int x,y,z;P(){}P(int _x,int _y,int _z){x=_x,y=_y;z=_z;}}op[N];
    struct E{int x,y,a,b;}e[M],q[N];
    inline bool cmpa(const E&a,const E&b){return a.a<b.a;}
    inline bool cmpe(int x,int y){return e[x].b<e[y].b;}
    inline bool cmpq(int x,int y){return q[x].b<q[y].b;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int F(int x){return f[x]==x?x:F(f[x]);}
    inline void merge(int x,int y,int a,int b,int type){
      x=F(x),y=F(y);
      if(x!=y){
        if(d[x]==d[y]){
          if(type)op[++co]=P(1,x,d[x]);
          d[x]++;
        }
        if(d[x]<d[y])swap(x,y);
        if(type)op[++co]=P(0,y,y);
        f[y]=x;
        if(va[x]<va[y]&&va[y]>a){
          if(type)op[++co]=P(2,x,va[x]);
          va[x]=va[y];
        }
        if(vb[x]<vb[y]&&vb[y]>b){
          if(type)op[++co]=P(3,x,vb[x]);
          vb[x]=vb[y];
        }
      }
      if(va[x]<a){
        if(type)op[++co]=P(2,x,va[x]);
        va[x]=a;
      }
      if(vb[x]<b){
        if(type)op[++co]=P(3,x,vb[x]);
        vb[x]=b;
      }
    }
    inline void retrace(){
      for(int i=co;i;i--){
        if(!op[i].x)f[op[i].y]=op[i].z;
        else if(op[i].x==1)d[op[i].y]=op[i].z;
        else if(op[i].x==2)va[op[i].y]=op[i].z;
        else vb[op[i].y]=op[i].z;
      }
      co=0;
    }
    int main(){
      read(n),read(m);
      while(lim*lim<m)lim++;
      for(i=1;i<=m;i++)read(e[i].x),read(e[i].y),read(e[i].a),read(e[i].b),a[i]=i;
      sort(e+1,e+m+1,cmpa);
      read(Q);
      for(i=1;i<=Q;i++)read(q[i].x),read(q[i].y),read(q[i].a),read(q[i].b);
      for(i=0;i<=m;i+=lim){
        cnt=0;
        for(j=1;j<=Q;j++)if(q[j].a>=e[i].a&&(i+lim>m||q[j].a<e[i+lim].a))b[++cnt]=j;
        if(!cnt)continue;
        sort(a+1,a+i+1,cmpe);
        sort(b+1,b+cnt+1,cmpq);
        for(j=1;j<=n;j++)f[j]=j,d[j]=0,va[j]=vb[j]=-1;
        for(j=k=1;j<=cnt;j++){
          while(k<=i&&e[a[k]].b<=q[b[j]].b){
            merge(e[a[k]].x,e[a[k]].y,e[a[k]].a,e[a[k]].b,0);
            k++;
          }
          co=0;
          for(o=min(i+lim-1,m);o>i;o--)
            if(e[o].a<=q[b[j]].a&&e[o].b<=q[b[j]].b)
              merge(e[o].x,e[o].y,e[o].a,e[o].b,1);
          x=F(q[b[j]].x),y=F(q[b[j]].y);
          if(x==y&&va[x]==q[b[j]].a&&vb[x]==q[b[j]].b)ans[b[j]]=1;
          retrace();
        }
      }
      for(i=1;i<=Q;i++)puts(ans[i]?"Yes":"No");
      return 0;
    }
    

      

  • 相关阅读:
    TensorFlow-Slim 简介+Demo
    AI 常见术语总结
    经典深度学习CNN总结
    YOLO V3 原理
    tf.app.run() 运行结束时,报错:SystemExit exception: no description
    VSCode中相对路径设置问题
    SSD算法原理
    机器学习-交叉熵原理
    tensorflow scope的作用
    水池进水和出水两个线程问题
  • 原文地址:https://www.cnblogs.com/clrs97/p/5406018.html
Copyright © 2020-2023  润新知