2017北京ICPC C题 Graph

#1629 : Graph

时间限制:4000ms
单点时限:4000ms
内存限制:256MB

描述

The country contains N cities numbered from 1 to N and M undirected roads connecting pairs of cities. There are some queries. Each query is represented by two numbers: L and R , meaning that all the cities whose number is between L and R(L and R are included) are safe, and other cities are not safe. We define city A can reach city B if and only if they are both safe and there exists a path from A to B that the cities on the path are all safe.

For each query, you need to figure out the number of pairs of cities that can reach each other under the condition given by the query.

输入

First line contains one number T which means the number of test cases.

For each test case, first line contains three numbers, above mentioned N , M and Q.

Next M lines, each line contains two integers: X, Y (X != Y) which means there is a road between city X and city Y (1 <= X,Y <= N).

Next Q lines, each line contains two numbers: L, R which indicates an query(1 <= L,R <= N, L <= R).

T <= 5, N , M <= 50000, Q <= 100000

输出

For each test case, output Q lines, each line contains the answer of the correspondent query.

样例输入
1
6 6 4
1 2
2 3
2 6
1 5
2 4
4 5
1 4
3 6
2 6
3 4
样例输出
6
1
10
0
分析:对于询问(L,R),可行的边(x,y)满足L<=x<=y<=R;
   那么分成两部分,满足L<=x的边与y<=R的边的交即可;
   于是把边拷贝两份分别排序求前缀交,可以离线用回滚莫队转移;
   维护答案用并查集即可;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define inf 0x3f3f3f3f
#define mod 19260817
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls (rt<<1)
#define rs (rt<<1|1)
#define all(x) x.begin(),x.end()
const int maxn=1e5+10;
const int N=2e5;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
int n,m,k,t,q,num,bl[maxn],fa[maxn],sz[maxn],cnt[2][maxn],tot,L[maxn],R[maxn];
ll ret,lst,ans[maxn];
struct node
{
    int u,v,id;
    bool operator<(const node&p)const
    {
        return bl[u]==bl[p.u]?v<p.v:bl[u]<bl[p.u];
    }
}e[maxn],f[maxn],qu[maxn],tmp[maxn];
bool cmp1(node x,node y)
{
    return x.u>y.u;
}
bool cmp2(node x,node y)
{
    return x.v<y.v;
}
int find(int x){return fa[x]==x?x:find(fa[x]);}
void unite(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return;
    if(sz[x]>sz[y])swap(x,y);
    fa[x]=y;
    ret+=(ll)sz[y]*sz[x];
    sz[y]+=sz[x];
}
void undo()
{
    while(tot)
    {
        int x=tmp[tot].u,y=tmp[tot].v;
        fa[x]=x;
        sz[y]-=sz[x];
        ret-=(ll)sz[y]*sz[x];
        tot--;
    }
}
int main(){
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&q);
        rep(i,1,m)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x>y)swap(x,y);
            e[i]=f[i]=node{x,y,i};
        }
        sort(e+1,e+m+1,cmp1);
        sort(f+1,f+m+1,cmp2);
        int pos=0;
        for(i=n;i>=1;i--)
        {
            while(pos+1<=m&&e[pos+1].u>=i)pos++;
            L[i]=pos;
        }
        pos=0;
        rep(i,1,n)
        {
            while(pos+1<=m&&f[pos+1].v<=i)pos++;
            R[i]=pos;
        }
        num=round(sqrt(m)+0.5);
        rep(i,1,m)bl[i]=(i-1)/num+1;
        rep(i,1,q)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x>y)swap(x,y);
            qu[i]=node{L[x],R[y],i};
        }
        sort(qu+1,qu+q+1);
        int l,r;
        rep(i,1,q)
        {
            if(i==1||bl[qu[i].u]!=bl[qu[i-1].u])
            {
                rep(j,1,n)fa[j]=j,sz[j]=1;
                rep(j,1,m)cnt[0][j]=cnt[1][j]=0;
                ret=tot=0;
                j=1;
                while(j<=m&&j<=bl[qu[i-1].u]*num)++cnt[0][e[j++].id];
                l=j,r=1;
            }
            while(r<=m&&r<=qu[i].v)
            {
                if(++cnt[1][f[r].id]==1&&cnt[0][f[r].id])
                {
                    unite(f[r].u,f[r].v);
                }
                r++;
            }
            lst=ret;
            while(l<=m&&l<=qu[i].u)
            {
                if(++cnt[0][e[l].id]==1&&cnt[1][e[l].id])
                {
                    int x=find(e[l].u),y=find(e[l].v);
                    if(x!=y)
                    {
                        if(sz[x]>sz[y])swap(x,y);
                        tmp[++tot]=node{x,y,0};
                        unite(x,y);
                    }
                }
                l++;
            }
            while(l>j)
            {
                --cnt[0][e[--l].id];
            }
            ans[qu[i].id]=ret;
            undo();
            ret=lst;
        }
        rep(i,1,q)printf("%lld
",ans[i]);
    }
    return 0;
}
/*
1
3 3 6
1 2
2 3
3 1
1 1
2 2
3 3
1 2
2 3
1 3
*/
原文地址:https://www.cnblogs.com/dyzll/p/7887249.html