根据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 ",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 ",ans,(int)c[j].id,c[j].v); 40 } 41 printf("%lld ",ans); 42 return 0; 43 }