zoukankan      html  css  js  c++  java
  • [BZOJ 4537][Hnoi 2016]最小公倍数

    传送门

    并查集+分块

    看到题目可以想到暴力做法,

    对于每个询问,

    将所有a和b小于等于询问值的的边加入图中(用并查集),

    如果询问的u和v在一个联通块中,

    且该联通块的maxa和maxb均等与询问的a和b,

    则答案为Yes。

    显然暴力是过不了的,于是可以用分块。

    将所有边按a值升序排序,分成√m 块操作,

    设每块第一条边为sp,每块长度为len,

    每次操作将edge[sp].a<=a<edge[sp+len].a的询问加入询问序列,

    将询问序列按b升序排列。

    对于边可以分成两部分:

      1、当前块之前的边;

      2、当前块的边;

    对于第一部分的边,其a值必定小于等于当前询问序列中的a值,

    所以按b升序排序后只要边的b值小于等于询问的b值就可以加进图中,

    这一部分的边加入后在处理下一个分块的询问之前都不用删(因为询问和边按b升序排序了);

    对于第二部分的边,暴力加上暴力删就可以了。

    至于如何暴力,开个栈把操作都记录下来就可以了。

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 
      4 using namespace std;
      5 
      6 #define N ((1<<16)-1)
      7 #define M ((1<<17)-1)
      8 #define Q ((1<<16)-1)
      9 
     10 int n,m,ep[M],qp[Q],ans[Q],q;
     11 
     12 struct E{
     13     int u,v,a,b;
     14     inline void read(){scanf("%d%d%d%d",&u,&v,&a,&b);}
     15 }e[M],que[Q];
     16 
     17 
     18 struct ACT_stack{
     19     int *pos[N],val[N],top;
     20     inline void push(int*p){pos[top]=p;val[top]=*p;top++;}
     21     inline void clear(){while (top) *pos[--top]=val[top];}
     22 }act;
     23 
     24 struct Union_Find_sets{
     25     int fa[N],dep[N],va[N],vb[N];
     26     int root(int x){return fa[x]==x?x:root(fa[x]);}
     27     inline void initialize(){for (int i=0;i<=n;i++)fa[i]=i,dep[i]=1,va[i]=-1,vb[i]=-1;}
     28     inline void merge(E&e,bool yes)
     29     {
     30         int x=root(e.u),y=root(e.v),tmp;
     31         if (x!=y)
     32         {
     33             if (dep[x]==dep[y])
     34             {
     35                 if (yes) act.push(&dep[x]);
     36                 dep[x]++;
     37             }
     38             if (dep[x]<dep[y]) swap(x,y);
     39             if (yes) act.push(&fa[y]);
     40             fa[y]=x;
     41         }
     42         tmp=max(va[y],e.a);
     43         if (tmp>va[x])
     44         {
     45             if (yes) act.push(&va[x]);
     46             va[x]=tmp;    
     47         }
     48         tmp=max(vb[y],e.b);
     49         if (tmp>vb[x])
     50         {
     51             if (yes) act.push(&vb[x]);
     52             vb[x]=tmp;    
     53         }
     54     }
     55 }ufs;
     56 
     57 void putin()
     58 {
     59     int i;
     60     scanf("%d%d",&n,&m);
     61     for (i=0;i<m;i++) {e[i].read();ep[i]=i;}
     62     scanf("%d",&q);
     63     for (i=0;i<q;i++) que[i].read();
     64 }
     65 
     66 inline bool cmp1(const E&a,const E&b){return a.a<b.a;}
     67 inline bool cmp2(int a,int b){return e[a].b<e[b].b;}
     68 inline bool cmp3(int a,int b){return que[a].b<que[b].b;}
     69 
     70 void answer()
     71 {
     72     int sp,i,j,ne,cnt,len=1,x,y;
     73     sort(e,e+m,cmp1);
     74     while (len*len<m)len++;
     75     for (sp=0;sp<m;sp+=len)
     76     {
     77         cnt=0;
     78         for (i=0;i<q;i++) 
     79             if (que[i].a>=e[sp].a&&(sp+len>=m||que[i].a<e[sp+len].a)) {qp[cnt++]=i;}
     80         if (!cnt) continue;
     81         sort(ep,ep+sp,cmp2);
     82         sort(qp,qp+cnt,cmp3);
     83         ufs.initialize();
     84         for (i=ne=0;i<cnt;i++)
     85         {
     86             while (ne<sp&&e[ep[ne]].b<=que[qp[i]].b)
     87                 ufs.merge(e[ep[ne++]],0);
     88             for (j=sp;j<min(sp+len,m);j++)
     89                 if (e[j].a<=que[qp[i]].a&&e[j].b<=que[qp[i]].b)
     90                     ufs.merge(e[j],1);
     91             x=ufs.root(que[qp[i]].u);
     92             y=ufs.root(que[qp[i]].v);
     93             if (x==y&&ufs.va[x]==que[qp[i]].a&&ufs.vb[x]==que[qp[i]].b) ans[qp[i]]=1;
     94             act.clear();
     95         }
     96     }    
     97     for (i=0;i<q;i++)
     98         printf(ans[i]?"Yes
    ":"No
    ");
     99 }
    100 
    101 int main()
    102 {
    103 //    freopen("multiple.in","r",stdin);
    104 //    freopen("multiple.out","w",stdout);
    105     putin();
    106     answer();
    107 //    fclose(stdin);
    108 //    fclose(stdout);
    109 }
    multiple
  • 相关阅读:
    交换相邻字符(CharBuffer)
    ANSI和UNICODE
    关键路径
    拓扑排序 java
    MySql 中group by使用
    面试题2
    面试题
    K8S如何限制资源使用
    Kubernetes中配置Pod的liveness和readiness探针
    sed入门详解教程
  • 原文地址:https://www.cnblogs.com/KaNNeXFF/p/5431541.html
Copyright © 2011-2022 走看看