2 条题解
-
0
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=2.5e+5; int A,B,n,m,a[N],b[N]; int main(){ scanf("%d%d%d%d",&A,&B,&n,&m); for(int i=1; i<=n; i++) scanf("%d",a+i); a[++n]=A; //横坐标 for(int i=1; i<=m; i++) scanf("%d",b+i); b[++m]=B; //竖坐标 sort(a+1,a+n+1); sort(b+1,b+m+1); for(int i=n; i>=1; i--) a[i]-=a[i-1]; //横边长 for(int i=m; i>=1; i--) b[i]-=b[i-1]; //竖边长 sort(a+1,a+n+1); sort(b+1,b+m+1); ll ans=1ll*a[1]*(m-1)+1ll*b[1]*(n-1); //m-1条最短横边,n-1条最短竖边 int i=2,j=2; while(i<=n && j<=m){ if(a[i]<b[j]) ans+=1ll*a[i++]*(m-j+1); //删短横边 else ans+=1ll*b[j++]*(n-i+1); //删短竖边 } printf("%lld\n",ans); } -
0
题目
如果此题数据要小一点,那么我们可以用克鲁斯卡尔算法通过,但是这个数据太大了,空间会爆炸,时间也会爆炸。
我们发现,如果用 MST 做,那么很多边的边权都一样,我们可以整行整列地删除。
我们造一个样例解析一下:
+-+--+---+ | | | | +-+--+---+ | | | | | | | | +-+--+---+首先,我们删除第一列的栅栏:
+-+--+---+ | | | | + +--+---+ | | | | | | | | +-+--+---+此时答案是 。
再删除第一排的栅栏:
+-+--+---+ | | + +--+---+ | | | | | | | | +-+--+---+此时答案是 。
我们继续删除第二列的栅栏:
+-+--+---+ | | + + +---+ | | | | | | | | +-+--+---+此时答案是 。
我们继续删除第二行的栅栏:
+-+--+---+ | | + + +---+ | | | | +-+--+---+此时答案是 。
我们把第三列的栅栏删除,由于之前删除的两行栅栏导致第三列栅栏少删除一个,不用删除。
你可以继续造更大的数据发现规律:
我们先把每一列,每一行的栅栏长度算出来,从小到达排序,然后用双指针算法,两个指针 和 ,第一个记录统计到哪一行,第二个记录统计到哪一列,这两个变量的初始值应该为 ,然后把第一列,第一行栅栏删除。讨论时,如果我们当前讨论的行比列要短,就删除 个栅栏,因为之前删除的栅栏导致我们现在不用删除一些栅栏。反之,同理,就是 个栅栏。如果一个指针走完了,那么所有的都是联通的,就不用再循环了。时间复杂度 ,通过。
AC Code:
#include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; int h, w, n, m; int a[300000], b[300000]; long long a1[300000], b1[300000]; long long ans; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> h >> w >> n >> m; for (int i = 1; i <= n; i ++) cin >> a[i]; for (int i = 1; i <= m; i ++) cin >> b[i]; sort(a + 1, a + n + 1); sort(b + 1, b + m + 1); n++; a[n] = h; m++; b[m] = w; for (int i = 1; i <= n; i ++) { a1[i] = a[i] - a[i - 1]; } for (int i = 1; i <= m; i ++) { b1[i] = b[i] - b[i - 1]; } sort(a1 + 1, a1 + n + 1); sort(b1 + 1, b1 + m + 1); // for (int i = 1; i <= n; i ++) { // cout << a1[i] << ' '; // } // cout << '\n'; // for (int j = 1; j <= m; j ++) { // cout << b1[j] << ' '; // } // cout << '\n'; int i = 2, j = 2; ans = a1[1] * (m - 1); ans += b1[1] * (n - 1); while (i <= n && j <= m) { if (a1[i] < b1[j]) { ans += a1[i] * (m - j + 1); i++; } else { ans += b1[j] * (n - i + 1); j++; } } cout << ans; return 0; }
- 1
信息
- ID
- 6695
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 12
- 已通过
- 1
- 上传者