• 2017icpcBeijing C


    题解: 首先查询的是边的编号在[l,r]的有效边  所以我们可以转化成将边的标号大于等于l的边与边的编号小于等于r的边求交集 则为查询的有效边 发现维护是用并查集维护 加边是Log 删边是on的  所以我们考虑离线以后回滚莫队处理答案即可 注意细节就行

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=1e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    typedef struct node{
        int l,r,id;
    }node;
    node st[MAXN];
    int tot;
    ll ans[MAXN];
    bool cmp1(node aa,node bb){
    	if(aa.l==bb.l)return aa.r>bb.r;
        return aa.l>bb.l;
    }
    bool cmp2(node aa,node bb){
        if(aa.r==bb.r)return aa.l<bb.l;
        return aa.r<bb.r;
    }
    node d1[MAXN],d2[MAXN],que[MAXN<<1];
    int f[MAXN],p[MAXN];
    int vis[MAXN],num[MAXN];
    vector<node>vec[MAXN];
    int find1(int x){
        if(x==f[x])return x;
        else return find1(f[x]);
    }
    int main(){
        int _=read();
        while(_--){
            int n,m,q;n=read();m=read();q=read();
            int sz=sqrt(m);memset(ans,0,sizeof(ans));
            inc(i,1,m)p[i]=(i-1)/sz+1,vec[i].clear();
            inc(i,1,n)f[i]=i,num[i]=1;
            int t1,t2;
            inc(i,1,m)t1=read(),t2=read(),d1[i].l=min(t1,t2),d1[i].r=max(t1,t2),d1[i].id=i,d2[i]=d1[i],vis[i]=0;
            inc(i,1,q)que[i].l=read(),que[i].r=read(),que[i].id=i,ans[i]=0;
            sort(d1+1,d1+m+1,cmp1);sort(d2+1,d2+m+1,cmp2);
            inc(i,1,q){
                int l=1;int r=m;int ans1=0;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(d1[mid].l>=que[i].l)l=mid+1,ans1=mid;
                    else r=mid-1;
                }
                if(ans1)vec[p[ans1]].pb(que[i]);
            }
            inc(i,1,p[m])sort(vec[i].begin(),vec[i].end(),cmp2);
            ll ans2=0;
            inc(i,1,p[m]){
                if(!vec[i].size()){
                    ans2=0;
                    for(int j=(i-1)*sz+1;j<=min(m,i*sz);j++){
                        vis[d1[j].id]++;
                    }
                    continue;
                }
                int L=(i-1)*sz+1;int R=1;
                for(int j=0;j<vec[i].size();j++){
                    while(R<=m&&d2[R].r<=vec[i][j].r){
                        vis[d2[R].id]++;
                        if(vis[d2[R].id]==2){
                            int t1=find1(d2[R].l);int t2=find1(d2[R].r);
                            if(t1!=t2){
                                if(num[t1]>num[t2])swap(t1,t2);
                                f[t1]=t2;
                                ans2+=1ll*num[t1]*num[t2];
                                num[t2]+=num[t1];
                            }
                        }
                        R++;
                    }
                    tot=0;
                    while(L<=m&&d1[L].l>=vec[i][j].l){
                        vis[d1[L].id]++;
                        if(vis[d1[L].id]==2){
                            int t1=find1(d1[L].l);int t2=find1(d1[L].r);
                            if(t1!=t2){
                                if(num[t1]>num[t2])swap(t1,t2);
                                f[t1]=t2;
                                ans2+=1ll*(num[t1])*num[t2];
                                num[t2]+=num[t1];
                                st[++tot]=(node){t1,t2,0};                          
                            }
                        }
                        L++;
                    }
                    ans[vec[i][j].id]=ans2;
                    while(tot){
                        f[st[tot].l]=st[tot].l;
                        num[st[tot].r]-=num[st[tot].l];
                        ans2-=1LL*num[st[tot].l]*num[st[tot].r];
                        tot--;
                    }
                    int tt=(i-1)*sz+1;
                    while(L>=tt){L--;vis[d1[L].id]--;}
                    vis[d1[L].id]++;L++; 
                }
                ans2=0;
                for(int j=1;j<=n;j++)f[j]=j,num[j]=1;
                for(int j=1;j<R;j++)if(vis[d2[j].id]>0)vis[d2[j].id]--;
                for(int j=(i-1)*sz+1;j<=min(m,i*sz);j++){
                    vis[d1[j].id]++;
                }
            }
            for(int i=1;i<=q;i++)printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    

     

    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.

    Input

    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

    Output

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

    Sample Input

    1
    6 6 4
    1 2
    2 3
    2 6
    1 5
    2 4
    4 5
    1 4
    3 6
    2 6
    3 4

    Sample Output

    6
    1
    10
    0
  • 相关阅读:
    Ckeditor事件绑定
    Linux使用netstat命令查看并发连接数
    memcached 常用命令及使用说明
    Linux(Ubuntu)下面SecureCRT 完全破解
    Linux下用SCP无需输入密码传输文件
    Java的URL类(一)
    java编码与解码(一)
    IDEA破解
    linux查看日志文件命令
    springboot +mybatis 搭建完整项目
  • 原文地址:https://www.cnblogs.com/wang9897/p/9882457.html
Copyright © 2020-2023  润新知