4537: [Hnoi2016]最小公倍数|分块

来源:互联网 发布:js修改input的value 编辑:程序博客网 时间:2024/06/04 00:33

暴力的做法就是直接找到所有a,b都小于等于某个询问的边然后并查集合并,维护每个集合的a,b得最大值看是否等于询问的a,b
然后就可以考虑分块,把边按照a排序,每隔n分为一块
块前的按照b值排序按顺序插入,块内的暴力判断,并查集合并,每次都把块内合并的记录下来,处理完某个询问时就撤回并查集的操作
块的大小为n可能会T 改成nlog2n可能会快一点

#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<vector>#include<cmath>#include<queue>#include<ctime>#include<set>#include<map>#define N 110000#define ll long longusing namespace std;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}struct W{int x,y,a,b,p;}a[N],q[N];int bl[N],c[N],fa[N],size[N],ma[N],mb[N];int st[N],SIZE[N],MA[N],MB[N],ans[N];int n,m,Q,top,cnt,block;bool cmp1(W a,W b){    return a.a<b.a||(a.a==b.a&&a.b<b.b);}bool cmp2(W a,W b){    return a.b<b.b||(a.b==b.b&&a.a<b.a);}int find(int x){    return x==fa[x]?x:find(fa[x]);}void merge(int x,int y,int a,int b,int v){    int fx=find(x);    int fy=find(y);    if(v==1)    {        ++cnt;        st[cnt]=fx;        MA[cnt]=ma[fx];        MB[cnt]=mb[fx];        SIZE[cnt]=size[fx];        ++cnt;        st[cnt]=fy;        MA[cnt]=ma[fy];        MB[cnt]=mb[fy];        SIZE[cnt]=size[fy];    }    if(fx==fy)    {        ma[fx]=max(ma[fx],a);        mb[fx]=max(mb[fx],b);    }    else    {        if(size[fx]<size[fy])swap(fx,fy);        fa[fy]=fx;        size[fx]+=size[fy];        ma[fx]=max(ma[fx],max(a,ma[fy]));        mb[fx]=max(mb[fx],max(b,mb[fy]));    }}void retract(){    for(int i=cnt;i>=1;i--)    {        int k=st[i];        fa[k]=k;        ma[k]=MA[i];        mb[k]=MB[i];        size[k]=SIZE[i];    }}int main(){    n=sc();m=sc();block=sqrt(m*log2(m));    for(int i=1;i<=m;i++)    {        a[i].x=sc();        a[i].y=sc();        a[i].a=sc();        a[i].b=sc();    }    Q=sc();    for(int i=1;i<=Q;i++)    {        q[i].x=sc();        q[i].y=sc();        q[i].a=sc();        q[i].b=sc();        q[i].p=i;    }    sort(a+1,a+m+1,cmp1);    sort(q+1,q+Q+1,cmp2);    for(int i=1;i<=m;i++)         bl[i]=(i-1)/block+1;    for(int i=1;i<=m;i+=block)    {        int top=0,now=1;        for(int j=1;j<=Q;j++)            if(q[j].a>=a[i].a&&(i+block>m||q[j].a<a[i+block].a))                c[++top]=j;        sort(a+1,a+i,cmp2);        for(int j=1;j<=n;j++)        {            fa[j]=j;            ma[j]=-1;            mb[j]=-1;            size[j]=1;        }        for(int j=1;j<=top;j++)        {            int k=c[j];            while(now<i&&a[now].b<=q[k].b)                 merge(a[now].x,a[now].y,a[now].a,a[now].b,0),now++;            for(int l=i;bl[l]==bl[i];l++)                if(a[l].a<=q[k].a&&a[l].b<=q[k].b)                     merge(a[l].x,a[l].y,a[l].a,a[l].b,1);            int fx=find(q[k].x),fy=find(q[k].y);            ans[q[k].p]=(fx==fy&&ma[fx]==q[k].a&&mb[fx]==q[k].b);            retract(); cnt=0;        }    }    for(int i=1;i<=Q;i++)        puts(ans[i]?"Yes":"No");    return 0;}
0 0
原创粉丝点击