嘘~ 正在从服务器偷取页面 . . .

SP27102 FN16SWAP - Swap Space 题解


SP27102 FN16SWAP - Swap Space 题解

题目链接:SP27102 FN16SWAP - Swap Space

题意

你管理着一个拥有多个计算机的大型集群,这些计算机上的硬盘使用各种不同的文件系统类型存储数据。最近,你决定将所有文件系统统一为相同类型。这是一个相当大的挑战,因为所有的硬盘目前都在使用中,它们都装满了重要数据,而且你不能承受任何数据丢失的风险。此外,将一个硬盘重新格式化为新的文件系统可能会显著改变其容量。为了使重新格式化成为可能,你将不得不购买一个额外的硬盘。显然,你希望通过尽量减小额外存储的大小来节省费用。

你可以以任何顺序重新格式化硬盘。在重新格式化一个硬盘之前,你必须将该硬盘上的所有数据移动到一个或多个其他硬盘上,必要时可以进行数据的分割。在一个硬盘重新格式化后,你可以立即开始使用它来存储来自其他硬盘的数据。并不需要将所有数据放在它们最初所在的硬盘上——事实上,如果某些硬盘在新的文件系统中具有较小的容量,这样做甚至可能是不可能的。同时,一些数据可能会被放在额外的硬盘上。

举个例子,假设你有四个硬盘 \(A\)\(B\)\(C\)\(D\),它们的容量(旧文件系统)分别为 \(6\)\(1\)\(3\)\(3\) \(\text{GB}\)。在新的文件系统下,它们的容量变为 \(6\)\(7\)\(5\)\(5\) \(\text{GB}\)。如果你只购买了 \(1\) \(\text{GB}\) 的额外空间,你可以将硬盘 \(B\) 上的数据移动到这里,然后重新格式化硬盘 \(B\)。现在,你在硬盘 \(B\) 上有 \(7\) \(\text{GB}\) 的空闲空间,所以你可以将硬盘 \(A\) 上的 \(6\) \(\text{GB}\) 数据移动到这里,并重新格式化硬盘 \(A\)。最后,你将来自硬盘 \(C\)\(D\) 的总共六个\(\text{GB}\)的数据移动到硬盘 \(A\) 上,并重新格式化硬盘 \(C\)\(D\)

输入格式

多个测试用例,直到输入结束为止。对于每个测试用例:

输入以包含一个整数 \(n\)\(1 \le n \le 10^6\))的行开始,表示你的集群中的硬盘数量。接下来的 \(n\) 行描述每个硬盘的容量,每行包含两个整数 \(a\)\(b\),其中 \(a\) 是旧文件系统下的容量,\(b\) 是新文件系统下的容量。

所有容量以\(\text{GB}\)为单位,并满足 \(1 \le a, b \le 10^9\)。(一千个PB应该足够大了,对吧?)

输出格式

对于每个测试用例,显示必须购买的额外容量(以\(\text{GB}\)为单位),以重新格式化硬盘。

依稀记得 Roundgod 老师说过的,贪心题,通常考虑两个不同元素,会优先选哪个。

我们先来考虑 \(x \le y\) 的元素。如果 \(x\) 相同,那么选哪个都一样。如果 \(y\) 相同,肯定选 \(x\) 小的。

然后考虑 \(x > y\) 的情况。如果 \(x\) 相同,不确定。如果 \(y\) 相同,肯定选 \(x\) 小的。

看上去我们没法确定两个 \(x\) 相等时的顺序,但是 \(y\) 的角度似乎还有路可走。

设两个元素 \(y_1 > y_2\) 。可以证明,如果先吃掉 \(y_1\) 再吃掉 \(y_2\) 不够时,即使先吃 \(y_2\) 也不可能够。

证明:设钱数为 \(t\) ,根据描述有 \(t - (x_1-y_1) < x_2\) ,则 \(t-(x_1-y_2) < x_2\)\(t-(x_2-y_2) < x_1\) \(\square\)

反之,先吃 \(y_2\) 的决策用脚想想都知道有反例。所以我们一定会优先选 \(y\) 大的。

因此我们只需要把 \(x\le y\) 的按 \(x\) 从小到大排序,\(x > y\) 的按 \(y\) 从大到小排序,然后扫一遍就好啦。

对了,关于 \(x>y\) 的情况,还有一种理解方式,就是比较难想到

考虑“时间倒流”,由减少变为增加,并根据 \(x\le y\) 的贪心策略得知此时加容量时要按 \(y\) 从小到大排序

时间复杂度 \(\mathcal{O}(n \log n)\)

代码:(三倍经验喵~)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
typedef pair<int,int> pii;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e6 + 15))
#define Fi first
#define Se second

pii a[N],b[N];
void solve(int n)
{
    int cnt1 = 0, cnt2 = 0;
    for(int i = 1, x,y; i <= n; i++)
    {
        if(cin >> x >> y, x > y) { 
            b[++cnt2] = make_pair(x, y); 
        } else { a[++cnt1] = make_pair(x, y); }
    }
    sort(a + 1, a + 1 + cnt1, [](pii x, pii y) { return x.Fi < y.Fi; });
    sort(b + 1, b + 1 + cnt2, [](pii x, pii y) { return x.Se > y.Se; });
    // int p = 0, k = 1; while(k) {
    //     if(!check(p + k)) { p += k, k <<= 1;} else k >>= 1;
    // }
    int res = 0, sum = 0; // 检查超支额度喵~
    for(int i = 1; i <= cnt1; i++) {
        up(res, a[i].Fi - sum), sum += a[i].Se - a[i].Fi;
    }
    for(int i = 1; i <= cnt2; i++) {
        up(res, b[i].Fi - sum), sum += b[i].Se - b[i].Fi;
    }
    cout << res << '\n';
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n; while(cin >> n) solve(n);
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录