[BZOJ4537]最小公倍数
容易想到对于每一个询问,将所有a<=A&&b<=B的边加入,用并查集维护联通性,并且维护联通块中a,b的最大值,
最后判断u,v是否联通并且a,b 的最大值是否等于A,B即可
因为不要求是简单路径,所以这样做是可行的
然后对于多个询问我们可以对边按a值分块
对于每个块,选出属于该块的询问,即A值在该块内的询问
对询问按b值排序
对于之前所有块和当前块也分别按b值排序
排序之后,对于之前所有块a值都满足要求,所以只要判断b值是否满足当前询问,若满足,加入并查集即可
然后对于当前块内的边同理
但当前块中满足这一个询问的边的a未必满足下一条询问,于是我们还要在并查集中删边
于是我们使用不带路径压缩的启发式合并并查集
使b值有序可以使用归并排序
还有还有,,,自己到自己不存在最小公倍数,于是维护联通块a,b最大值的数组初值应赋为-1
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define fir first 4 #define sec second 5 #define mp make_pair 6 #define pb push_back 7 #define inf 0x3f3f3f3f 8 #define maxn 50005 9 #define maxm 100005 10 struct node{ int u,v,ic,id,a,b; }R[maxm],Q[maxn]; 11 int n,m,q,ans[maxn],fa[maxn],sz[maxn],mx[maxn][2]; 12 vector<int>blc,haha; 13 vector<pair<int,int> >rng; 14 vector<node>cur,lst,tmp,op; 15 int read(){ 16 int ttt=0; char ch=0; 17 while(ch<'0'||ch>'9')ch=getchar(); 18 while(ch>='0'&&ch<='9')ttt=ttt*10+ch-'0',ch=getchar(); 19 return ttt; 20 } 21 bool cmp1(node x,node y){ return x.a<y.a; } 22 bool cmp2(node x,node y){ return x.b<y.b; } 23 void getblock(){ 24 sort(R+1,R+1+m,cmp1); 25 int ele=sqrt(m); 26 for(int i=1;i<=m;i++) 27 blc.pb(R[min(i+=ele-1,m)].a); 28 blc.pop_back(),blc.pb(inf); 29 sort(Q+1,Q+1+q,cmp1); 30 int j=1; 31 for(int i=0;i<(int)blc.size();i++){ 32 int bf=j; 33 while(j<=q&&Q[j].a<blc[i])j++; 34 rng.pb(mp(bf,j-1)); 35 } 36 } 37 int gf(int x){ return fa[x]==x?x:gf(fa[x]); } 38 void un(node P,int flag){ 39 int u=gf(P.u),v=gf(P.v); 40 if(u!=v){ 41 if(sz[u]<sz[v]){ 42 if(flag)op.pb((node){u,v,sz[u],sz[v],mx[v][0],mx[v][1]}); 43 fa[u]=v,sz[v]+=sz[u]; 44 mx[v][0]=max(max(mx[u][0],mx[v][0]),P.a); 45 mx[v][1]=max(max(mx[u][1],mx[v][1]),P.b); 46 } 47 else{ 48 if(flag)op.pb((node){u,v,sz[u],sz[v],mx[u][0],mx[u][1]}); 49 fa[v]=u,sz[u]+=sz[v]; 50 mx[u][0]=max(max(mx[u][0],mx[v][0]),P.a); 51 mx[u][1]=max(max(mx[u][1],mx[v][1]),P.b); 52 } 53 } 54 else{ 55 if(flag)op.pb((node){u,v,sz[u],sz[v],mx[u][0],mx[u][1]}); 56 mx[u][0]=max(max(mx[u][0],mx[v][0]),P.a); 57 mx[u][1]=max(max(mx[u][1],mx[v][1]),P.b); 58 } 59 } 60 void baoliun(int x){ 61 for(int i=0;i<(int)cur.size()&&cur[i].b<=Q[x].b;i++) 62 if(cur[i].a<=Q[x].a)un(cur[i],1); 63 } 64 void baolibk(){ 65 for(int i=(int)op.size()-1;i>=0;i--){ 66 int u=op[i].u,v=op[i].v; 67 fa[u]=u,fa[v]=v; 68 sz[u]=op[i].ic,sz[v]=op[i].id; 69 if(sz[u]<sz[v])mx[v][0]=op[i].a,mx[v][1]=op[i].b; 70 else mx[u][0]=op[i].a,mx[u][1]=op[i].b; 71 } 72 op.clear(); 73 } 74 void merge(){ 75 tmp=lst,lst.clear(); 76 int i=0,j=0; 77 while(i<(int)tmp.size()&&j<(int)cur.size()){ 78 if(tmp[i].b<cur[j].b)lst.pb(tmp[i++]); 79 else lst.pb(cur[j++]); 80 } 81 while(i<(int)tmp.size())lst.pb(tmp[i++]); 82 while(j<(int)cur.size())lst.pb(cur[j++]); 83 } 84 void getans(int l,int r){ 85 for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1; 86 memset(mx,-1,sizeof(mx)); 87 int j=0; 88 for(int i=l;i<=r;i++){ 89 while(j<(int)lst.size()&&lst[j].b<=Q[i].b)un(lst[j++],0); 90 baoliun(i); 91 int u=gf(Q[i].u),v=gf(Q[i].v); 92 if(u==v&&mx[u][0]==Q[i].a&&mx[u][1]==Q[i].b)ans[Q[i].id]=1; 93 baolibk(); 94 } 95 merge(); 96 } 97 void solve(){ 98 getblock(); 99 int j=1; 100 for(int i=0;i<(int)blc.size();i++){ 101 cur.clear(); 102 while(j<=m&&R[j].a<=blc[i])cur.pb(R[j++]); 103 sort(cur.begin(),cur.end(),cmp2); 104 sort(Q+rng[i].fir,Q+rng[i].sec+1,cmp2); 105 getans(rng[i].fir,rng[i].sec); 106 } 107 } 108 int main(){ 109 n=read(),m=read(); 110 for(int i=1;i<=m;i++) 111 R[i].u=read(),R[i].v=read(),R[i].a=read(),R[i].b=read(); 112 q=read(); 113 for(int i=1;i<=q;i++){ 114 Q[i].u=read(),Q[i].v=read(),Q[i].a=read(),Q[i].b=read(); 115 Q[i].id=i; 116 } 117 solve(); 118 for(int i=1;i<=q;i++) 119 puts(ans[i]?"Yes":"No"); 120 return 0; 121 }