zoukankan      html  css  js  c++  java
  • bzoj4410 [Usaco2016 Feb] Fence in

    Description

    有一个平面,左下角是(0,0),右上角是(A,B)。
    有n个平行于y轴的栅栏a1..an,表示挡在(ai,0)到(ai,B)之间。
    有m个平行于x轴的栅栏b1..bn,表示挡在(0,bi)到(A,bi)之间。
    这样,平面被划成了(n+1)*(m+1)块。
    现在要去掉某些栅栏的一部分,使得每一块都连通。
    比如原来是这样:

    可以去掉后变成这样:

    求最少需要去掉多少长度的栅栏使得每一块都连通。

    Input

    第一行四个数A,B,n,m。
    A<=1000000000 ,B<=1000000000 N<=25000 M<=25000
    接下来n行每行一个数表示ai
    接下来m行每行一个数表示bi。
    0<ai<A  0<bi<B 

    Output

    输出一个数表示答案。
     
    对边长排序后从小到大加边求最小生成树,一次加边加一行或一列,注意由于一部分可能已经连通,加边时要减去不需要加的边。
    时间复杂度O(nlogn+mlogm+n+m)
    #include<cstdio>
    #include<algorithm>
    int A,B,n,m;
    int ns[25005],ms[25005];
    int pn=0,pm=0;
    long long ans=0;
    inline int read(){
        int x=0,c=getchar();
        while(c>'9'||c<'0')c=getchar();
        while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
        return x;
    }
    int main(){
        A=read();B=read();n=read();m=read();
        ns[0]=ms[0]=0;
        ns[n+1]=B;
        ms[m+1]=A;
        for(int i=1;i<=n;i++)ns[i]=read();
        for(int i=1;i<=m;i++)ms[i]=read();
        std::sort(ns,ns+n+2);
        std::sort(ms,ms+m+2);
        for(int i=0;i<=n;i++)ns[i]=ns[i+1]-ns[i];
        for(int i=0;i<=m;i++)ms[i]=ms[i+1]-ms[i];
        n++;m++;
        std::sort(ns,ns+n);
        std::sort(ms,ms+m);
        while(pn<n&&pm<m){
            if(ns[pn]<ms[pm])ans+=ns[pn]*1ll*(pm&&pn?m-pm:m-1),pn++;
            else ans+=ms[pm]*1ll*(pn&&pm?n-pn:n-1),pm++;
        }
        while(pn<n)ans+=ns[pn]*1ll*(pm&&pn?m-pm:m-1),pn++;
        while(pm<m)ans+=ms[pm]*1ll*(pn&&pm?n-pn:n-1),pm++;
        printf("%lld
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    Java中Comparable与Comparator的区别
    LeetCode[5] 最长的回文子串
    LeetCode[3] Longest Substring Without Repeating Characters
    LeetCode 7. Reverse Integer
    统计单词出现的次数
    System.arraycopy()和Arrays.copyOf()的区别
    SyncToy
    查看端口占用及进程号
    TCP协议
    python 的日志logging模块学习
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5239834.html
Copyright © 2011-2022 走看看