hdu4677 Query on Graph 根号n

根号n区间暴力神技。。。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
    int l,r,id1,id2;
    bool operator< (const node& a) const
    {
        return id1==a.id1?r<a.r:id1<a.id1;
    }
}q[30005];
struct edge
{
    int to,next;
}ee[30005*3*2];
int e[30005],ecnt;
void addedge(int u,int v)
{
    ee[ecnt].to=v;ee[ecnt].next=e[u];e[u]=ecnt++;
    ee[ecnt].to=u;ee[ecnt].next=e[v];e[v]=ecnt++;
}
int f1[30005],f2[30005],f3[30005],visit[30005];
int find1(int id)
{
    if(f1[id]==id)
        return id;
    return f1[id]=find1(f1[id]);
}
bool merge1(int x,int y)
{
    if(find1(x)==find1(y))
        return false;
    f1[f1[x]]=f1[y];
    return true;
}
int find2(int id)
{
    if(f2[id]==id)
        return id;
    return f2[id]=find2(f2[id]);
}
bool merge2(int x,int y)
{
    if(find2(x)==find2(y))
        return false;
    f2[f2[x]]=f2[y];
    return true;
}
int find3(int x,int id)
{
    if(visit[x]!=id)
    {
        visit[x]=id;f3[x]=f2[x];
    }
    if(f3[x]==x)
        return x;
    return f3[x]=find3(f3[x],id);
}
bool merge3(int x,int y,int id)
{
    if(find3(x,id)==find3(y,id))
        return false;
    f3[f3[x]]=f3[y];
    return true;
}
int ans[30005],n1,m,n2,ms;
void solve()
{
    int i,j,k,kk,u,v,mn,anss,anss2;
    memset(visit,0,sizeof(visit));
    for(i=1;i<=n2;)
    {
        mn=q[i].id1;
        for(;i<=n2&&q[i].id1==mn&&q[i].r<=mn*ms;++i)
        {
            anss=q[i].r-q[i].l+1;
            for(j=q[i].l;j<=q[i].r;++j)
            {
                f1[j]=j;
            }
            for(j=q[i].l;j<=q[i].r;++j)
            {
                u=j;
                for(k=e[j];k!=-1;k=ee[k].next)
                {
                    v=ee[k].to;
                    if(v<=q[i].r&&v>=q[i].l)
                    {
                        if(merge1(u,v))
                            anss--;
                    }
                }
            }
            ans[q[i].id2]=anss;
        }
        if(i>n2||q[i].id1!=mn)
            continue;
        anss=0;
        for(j=mn*ms+1;j<=n1;++j)
        {
            f2[j]=j;anss++;
        }
        for(j=mn*ms+1;i<=n2&&q[i].id1==mn;++i)
        {
            for(;j<=q[i].r;++j)
            {
                u=j;
                for(k=e[j];k!=-1;k=ee[k].next)
                {
                    v=ee[k].to;
                    if(v<=u&&v>=mn*ms+1)
                    {
                        if(merge2(u,v))
                            anss--;
                    }
                }
            }
            anss2=anss-(n1-q[i].r);
            for(k=q[i].l;k<=mn*ms;++k)
            {
                f3[k]=k;visit[k]=i;
                anss2++;
            }
            for(k=q[i].l;k<=mn*ms;++k)
            {
                u=k;
                for(kk=e[k];kk!=-1;kk=ee[kk].next)
                {
                    v=ee[kk].to;
                    if(v<=q[i].r&&v>=q[i].l)
                    {
                        if(merge3(u,v,i))
                        {
                            anss2--;
                        }
                    }
                }
            }
            ans[q[i].id2]=anss2;
        }
    }
}
int main()
{
    int t,cas=0,i,j,u,v;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n1,&m);
        ms=sqrt(1.0*n1);
        memset(e,-1,sizeof(e));ecnt=0;
        for(i=1;i<=m;++i)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        scanf("%d",&n2);
        for(i=1;i<=n2;++i)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id2=i;q[i].id1=(q[i].l-1)/ms+1;
        }
        sort(q+1,q+1+n2);
        solve();
        printf("Case #%d:\n",++cas);
        for(i=1;i<=n2;++i)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值