P3141 [USACO16FEB]围栏Fenced In_Platinum
题目描述
Farmer John has realized that many of his cows are strangely agoraphobic (being fearful of large open spaces). To try and make them less afraid of grazing, he partitions his large field into a number of smaller regions by building vertical (north-south) and horizontal (east-west) fences.
The large field is a rectangle with corner points at (0,0)(0,0)(0,0) and (A,B)(A,B)(A,B) . FJ builds nnn vertical fences ( 0≤n≤25,0000 \leq n \leq 25,0000≤n≤25,000 ) at distinct locations a1…ana_1 \ldots a_na1…an ( 0<ai<A0 < a_i < A0<ai<A ); each fence runs from (ai,0)(a_i, 0)(ai,0) to (ai,B)(a_i, B)(ai,B) . He also builds mmm horizontal fences ( 0≤m≤25,0000 \leq m \leq 25,0000≤m≤25,000 ) at locations b1…bmb_1 \ldots b_mb1…bm ( 0<bi<B0 < b_i < B0<bi<B ); each such fence runs from (0,bi)(0, b_i)(0,bi) to (A,bi)(A, b_i)(A,bi) . Each vertical fence crosses through each horizontal fence, subdividing the large field into a total of (n+1)(m+1)(n+1)(m+1)(n+1)(m+1) regions.
Unfortunately, FJ completely forgot to build gates into his fences, making it impossible for cows to leave their enclosing region and travel around the entire field! He wants to remedy this situation by removing pieces of some of his fences to allow cows to travel between adjacent regions. He wants to select certain pairs of adjacent regions and remove the entire length of fence separating them; afterwards, he wants cows to be able to wander through these openings so they can travel anywhere in his larger field.
For example, FJ might take a fence pattern looking like this:
+---+--+
| | |
+---+--+
| | |
| | |
+---+--+
and open it up like so:
+---+--+
| |
+---+ +
| |
| |
+---+--+
Please help FJ determine the minimum total length of fencing he must remove to accomplish his goal.
有一个平面,左下角是(0,0),右上角是(A,B)。
有n个平行于y轴的栅栏a1..an,表示挡在(ai,0)到(ai,B)之间。
有m个平行于x轴的栅栏b1..bn,表示挡在(0,bi)到(A,bi)之间。
这样,平面被划成了(n+1)*(m+1)块。
现在要去掉某些栅栏的一部分,使得每一块都连通。
比如原来是这样:
+---+--+
| | | +---+--+
+---+--+
可以去掉后变成这样:
+---+--+
| |
+---+ +
+---+--+
求最少需要去掉多少长度的栅栏使得每一块都连通。
输入输出格式
输入格式:The first line of input contains AAA , BBB , nnn , and mmm
( 1≤A,B≤1,000,000,0001 \leq A, B \leq 1,000,000,0001≤A,B≤1,000,000,000 ). The next nnn lines contain a1…ana_1 \ldots a_na1…an ,
and the next mmm lines after that contain b1…bmb_1 \ldots b_mb1…bm .
输出格式:Please write the minimum length of fencing FJ must remove. Note that this might
be too large to fit into a standard 32-bit integer, so you may need to
use 64-bit integer types (e.g., "long long" in C/C++).
输入输出样例
15 15 5 2
2
5
10
6
4
11
3
44
Solution:
本题好考思维啊!
题意是一个$A*B$的矩形,被$n$条平行于$y$轴的直线和$m$条平行于$x$轴的直线,分为$(n+1)*(m+1)$个矩形,现在要删去长度最小的边(任意两个矩形之间的某条边),使得原矩形内部连通。
我们可以先画画图,不难归纳出,要使矩形内部连通至少需要删去$(n+1)*(m+1)-1$条边,这个式子可以理解为每个小矩形要与其它小矩形互通,至少删去$1$条边,而只要使$(n+1)*(m+1)-1$个矩形互通,就能使大矩形内部互通(因为最后一个小矩形必定有条边在之前的矩形中已被删去)。
那么我们很快可以有个初步的思路,我们可以先处理出所有的$n+1$条平行$x$轴的边,和$m+1$条平行于$y$轴的边(然后直接$n++,\;m++$),贪心的想到,先删去当前最短的一条边,若是平行于$x$轴就删去$m-j+1$条该边,若是平行于$y$轴就删去$n-i+1$条该边($i$为所有平行于$x$轴的边从小到大排序后的编号,$j$含义类似),为什么是$m-j+1$和$n-i+1$呢?因为我们每次删边后,与其垂直的边就能少删$1$条,具体来说:
1、当$x[i]<y[j]$的时候,肯定要删第$i$列的水平栅栏,该列的栅栏个数为$m$(行数)$-j$(已经删了多少行)$+1$,对列有影响的是行(列与列不相交)
2、当$x[i]>y[j]$的时候,肯定要删第$j$行的竖直栅栏,该行的栅栏个数为$n$(列数)$-i$(已经删了多少列)$+1$,对行有影响的是列(行与行不相交)
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) using namespace std; ll A,B,ans,n,m,x[25005],y[25005],a[25005],b[25005]; il ll gi(){ ll a=0;char x=getchar(); while(x<'0'||x>'9')x=getchar(); while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); return a; } int main(){ A=gi();B=gi();n=gi();m=gi(); For(i,1,n)a[i]=gi(); For(i,1,m)b[i]=gi(); sort(a+1,a+n+1),sort(b+1,b+m+1); For(i,1,n)x[i]=a[i]-a[i-1];x[n+1]=A-a[n++]; For(i,1,m)y[i]=b[i]-b[i-1];y[m+1]=B-b[m++]; sort(x+1,x+n+1),sort(y+1,y+m+1); ans=x[1]*(m-1)+y[1]*(n-1); for(int i=2,j=2;i<=n&&j<=m;) if(x[i]<y[j])ans+=x[i++]*(m-j+1); else ans+=y[j++]*(n-i+1); cout<<ans; return 0; }