[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 }
View Code

 

posted @ 2016-04-22 20:03  Ngshily  阅读(378)  评论(0编辑  收藏  举报