BZOJ4410: [Usaco2016 Feb]Fence in

 

 

偶尔来道奶牛题休闲一下。

$a \leq 1e9$,$b \leq 1e9$,$a*b$的大矩形中有$n \leq 25000$条竖栏杆$m \leq 25000$条横栏杆(a对n,b对m),这些栏杆是无限长的且互不重合。给竖栏杆的横坐标和横栏杆的纵坐标。现在这些栏杆把矩形隔成很多块,问移除最短多长的子栏杆使得所有小矩形连通。如下图。

------>

用最小生成树的想法,贪心选最小的来割。于是两边栏杆排个序,一个一个加答案即可。

具体这么割:比如你要割横的(注意这里的横的是n竖的是m)

一开始切两组(不如说颜色)蓝的:

然后要切一组红的。虽然之前切了蓝的,但这两条蓝的行还没连通,因此还是要切2条:

现在又要切条红的。注意,现在那两条蓝行的已经连通,因此可以少切一条:

诸如此类,分一下是不是第一次切这个方向(颜色)的边即可,如果不是就可以减掉另一方向已经连通的数量。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<vector>
 6 //#include<queue>
 7 //#include<time.h>
 8 //#include<complex>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 int n,m,A,B;
14 #define maxn 25011
15 int a[maxn],b[maxn];
16 #define LL long long
17 int main()
18 {
19     scanf("%d%d%d%d",&A,&B,&n,&m);
20     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
21     sort(a+1,a+1+n);
22     a[n+1]=A-a[n]; for (int i=n;i;i--) a[i]=a[i]-a[i-1]; n++;
23     for (int i=1;i<=m;i++) scanf("%d",&b[i]);
24     sort(b+1,b+1+m);
25     b[m+1]=B-b[m]; for (int i=m;i;i--) b[i]=b[i]-b[i-1]; m++;
26     
27     sort(a+1,a+1+n);
28     sort(b+1,b+1+m);
29     int p=1,q=1;
30     LL ans=0;
31     a[n+1]=b[m+1]=0x3f3f3f3f;
32     while (p<=n || q<=m)
33         if (a[p]<b[q]) ans+=1ll*a[p]*(m-1-(p>1)*(q==1?0:q-2)),p++;
34         else ans+=1ll*b[q]*(n-1-(q>1)*(p==1?0:p-2)),q++;
35     printf("%lld\n",ans);
36     return 0;
37 }
View Code

 

posted @ 2018-03-21 16:42  Blue233333  阅读(122)  评论(0编辑  收藏  举报