bzoj4537: [Hnoi2016]最小公倍数

来源:互联网 发布:php个人自动发卡源码 编辑:程序博客网 时间:2024/06/02 06:28

传送门: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;}



0 0
原创粉丝点击