您的位置:首页 > 其它

bzoj4537: [Hnoi2016]最小公倍数

2016-04-20 19:35 316 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4537

思路:把边按a排序,每sqrt(m)分一组

然后把询问按b排序,把在这组及以前的边按b排序

把这些边用并查集一条一条插入并维护

零散的部分暴力插入并记录,做完后暴力撤销

注意:并查集不能路径压缩,否则无法撤销回去

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int maxn=100010;
using namespace std;
int n,m,S,Q,top,f[maxn],maxa[maxn],maxb[maxn],ans[maxn],opcnt,siz[maxn];
struct data{
int x,y,a,b,id;
void init(int i){id=i,scanf("%d%d%d%d",&x,&y,&a,&b);}
void print(){printf("%d %d %d %d %d\n",x,y,a,b,id);}
}e[maxn],q[maxn],stk[maxn];
struct oper{int x,y,f,maxa,maxb,siz;}op[maxn];
bool operator <(data x,data y){return x.a==y.a?x.b<y.b:x.a<y.a;}
bool cmp(data x,data y){return x.b==y.b?x.a<y.a:x.b<y.b;}
int find(int x){return f[x]==x?x:find(f[x]);}

void merge(int x,int y,int a,int b){
x=find(x),y=find(y);
if (siz[x]>siz[y]) swap(x,y);
op[++opcnt]=(oper){x,y,f[x],maxa[y],maxb[y],siz[y]};
if (x==y){maxa[y]=max(maxa[y],a),maxb[y]=max(maxb[y],b);return;}
f[x]=y,siz[y]+=siz[x];
maxa[y]=max(maxa[x],max(maxa[y],a));
maxb[y]=max(maxb[x],max(maxb[y],b));
}

void goback(){
for (int i=opcnt;i;i--){
int x=op[i].x,y=op[i].y;
f[x]=op[i].f,maxa[y]=op[i].maxa,maxb[y]=op[i].maxb,siz[y]=op[i].siz;
}
opcnt=0;
}

int main(){
scanf("%d%d",&n,&m),S=(int)sqrt(m);
for (int i=1;i<=m;i++) e[i].init(i);
sort(e+1,e+1+m);
//for (int i=1;i<=m;i++) e[i].print();
scanf("%d",&Q);
for (int i=1;i<=Q;i++) q[i].init(i);
sort(q+1,q+1+Q,cmp);
//for (int i=1;i<=Q;i++) q[i].print();
for (int i=1;i<=m;i+=S){
top=0;
for (int j=1;j<=Q;j++)
if (q[j].a>=e[i].a&&(i+S>m||q[j].a<e[i+S].a))
stk[++top]=q[j];
//printf("\ni: %d\n",i);for (int j=1;j<=top;j++) stk[j].print();
sort(e+1,e+1+i,cmp);
for (int j=1;j<=n;j++) f[j]=j,maxa[j]=maxb[j]=-1,siz[j]=1;
for (int j=1,k=1;j<=top;j++){
for (;k<i&&e[k].b<=stk[j].b;k++)
merge(e[k].x,e[k].y,e[k].a,e[k].b);
opcnt=0;
for (int l=i;l<i+S&&l<=m;l++)
if (e[l].a<=stk[j].a&&e[l].b<=stk[j].b)
merge(e[l].x,e[l].y,e[l].a,e[l].b);
int x=find(stk[j].x),y=find(stk[j].y);
ans[stk[j].id]=(x==y&&maxa[x]==stk[j].a&&maxb[x]==stk[j].b);
goback();
}
}
for (int i=1;i<=Q;i++) puts(ans[i]?"Yes":"No");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: