[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\n":"No\n"); 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 }