[bzoj4410] [Usaco2016 Feb]Fence in

  根据ccz181078大爷的题解可得(QAQ,每次肯定是断掉连续一行||一列的栅栏。。。

  贪心地想,一个格子与外面联通,显然是先把短的边界断掉(就像mst那样

  但是比较蛋疼的是,因为我们每次断的时候,有一些点可能已经联通了,所以有的栅栏不用断>_<

  如果我们断了x列栅栏,并且之前有断过行的栅栏,那么下一次断开行的时候,那一行上的联通块个数就是n-x+1。。(假设有n行

  列上的联通块个数同理

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int maxn=25233;
 8 struct zs{
 9     int v;bool id;
10 }c[maxn<<1];
11 int a[maxn],b[maxn],A,B;
12 int numh,numl,smh,sml;//numh,numl:当前已连了多少行、列。smh,smhl:每行||列有多少个联通块 
13 int i,j,k,n,m;
14 ll ans;
15  
16 int ra;char rx;
17 inline int read(){
18     rx=getchar(),ra=0;
19     while(rx<'0'||rx>'9')rx=getchar();
20     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
21 }
22 bool cmp(zs a,zs b){return a.v<b.v;}
23 int main(){
24     A=read(),B=read(),n=read(),m=read();
25     for(i=1;i<=n;i++)a[i]=read();a[n+1]=A;
26     for(i=1;i<=m;i++)b[i]=read();b[m+1]=B;
27     sort(a+1,a+1+n);sort(b+1,b+1+m);
28     n++,m++;
29     for(i=n;i;i--)c[i].v=a[i]-a[i-1],c[i].id=0;
30     for(i=m;i;i--)c[i+n].v=b[i]-b[i-1],c[i+n].id=1;
31     sort(c+1,c+1+n+m,cmp);
32     smh=n,sml=m;j=0;
33     while(smh>1||sml>1){
34         j++;//printf("  %d %d\n",sml,smh);
35         if(!c[j].id)ans+=(ll)(sml-1)*c[j].v,numl++;
36         else ans+=(ll)(smh-1)*c[j].v,numh++;
37         if(numl)sml=min(m,m-numh+1);
38         if(numh)smh=min(n,n-numl+1);
39     //  printf(" ans:%lld   %d %d\n",ans,(int)c[j].id,c[j].v);
40     }
41     printf("%lld\n",ans);
42     return 0;
43 }
View Code

 

posted @ 2016-03-21 13:38  czllgzmzl  阅读(293)  评论(0编辑  收藏  举报