根号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;
}