zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    分类和预测
    机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理)
    字符串匹配的KMP算法
    灰度共生矩阵提取纹理特征源码
    redis永不过期,保留最新5条数据,StringUtils.join()等总结
    Session问题以及解决方案
    spring boot 配置 log4j2
    每日知识记载总结54
    spring cloud踩坑指南
    每日知识记载总结53
  • 原文地址:https://www.cnblogs.com/wang9897/p/9882457.html
Copyright © 2011-2022 走看看