• BZOJ 4619 Swap Space 解题报告


    今天是因为David Lee正好讲这个题的类似题,我才做了一下。

    本题是world final 2016的一道水……

    题目地址如下

    http://www.lydsy.com/JudgeOnline/problem.php?id=4619.

    这道题目让我们求为格式化所有硬盘所需要买的最小的额外空间。

    这道题目很容易能看出来是一道贪心题目(据David Lee说还有一种做法是二分+贪心,不过qdez的师天硕stonepage和我Icontofig都觉得二分+贪心有些麻烦,然而stonepage不打算写,那就由我来写这一篇题解报告)。

    那我们该怎么贪心呢?

    第一种想法:我们看格式化后与格式化前的差值的大小来拍一遍序,然后加起来(剩余空间)看看最后我们需要多少额外空间(剩余空间是负数)。这个想法很容易被Hack掉,自己手写一组加起来大于0的就可以Hack,因为你一开始的磁盘空间是0

    第二种想法:我们先把格式化后与格式化前的差值大于0的加在一起,然后再根据每个磁盘的a值升序操作剩下的。这个也很容易hack掉,比如突然就来了一个格式化前空间非常大的,这种做法就懵逼了。

    第三种想法:那我把第二种想法倒过来,行不行呢?显然不行,有些数据随随便便就可以hack掉你。

    那应该怎么做?

    正解:

    我们对于输入的数据进行预处理,把格式化后与格式化前的差值大于0的放在一个结构体里面,把小于0的放在一个结构体里。

    先处理大于0的,对其根据b值进行升序排列,然后模拟过程(设一开始的剩余空间为0),用sum记录过程中出现的最小负值,再用ans记录剩余空间(就是待会儿程序里面的co)。

    再处理小于0的,同上操作(不过这时候剩余空间不是0了,上面操作已经更改过了);

    然后sum的绝对值就是我们想要的答案啦!具体证明明天我再问问stonepage;

    具体代码如下

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <cstdlib>
     7 using namespace std;
     8 typedef long long LL;
     9 const int maxn = 1000005;
    10 struct SD{
    11     LL a,d;
    12 }p[maxn];
    13 struct counter{
    14     LL a,b,co;
    15 }pluss[maxn],dece[maxn];
    16 bool cmp1(counter a,counter b){
    17     return a.b < b.b;
    18 }
    19 bool cmp2(counter a,counter b){
    20     return a.a > b.a;
    21 }
    22 LL n,ans,sum,now1,now2;
    23 LL get_num(){
    24     LL num = 0;
    25     char c;
    26     bool flag = false;
    27     while((c = getchar()) == ' ' || c == '
    ' || c == '
    ');
    28     if(c == '-')flag = true;
    29     else num = c - '0';
    30     while(isdigit(c = getchar()))
    31         num = num * 10 + c - '0';
    32     return (flag ? -1 : 1) * num;
    33 }
    34 void init(){
    35     memset(p,0,sizeof(p));
    36     memset(pluss,0,sizeof(pluss));
    37     memset(dece,0,sizeof(dece));
    38     now1 = now2 = 0;
    39 }
    40 int main(){
    41     init();
    42     n = get_num();
    43     for(int i = 1;i <= n;++i){
    44         p[i].d = get_num();
    45         p[i].a = get_num();
    46         if(p[i].a >= p[i].d){
    47             pluss[++now1].a = p[i].a;
    48             pluss[now1].b = p[i].d;
    49             pluss[now1].co = p[i].a - p[i].d;
    50         }
    51         else{
    52             dece[++now2].a = p[i].a;
    53             dece[now2].b = p[i].d;
    54             dece[now2].co = p[i].a - p[i].d;
    55         }
    56     }
    57     sort(pluss+1,pluss+now1+1,cmp1);
    58     sort(dece+1,dece+now2+1,cmp2);
    59     for(int i = 1;i <= now1;++i){
    60         sum = min(sum,ans - pluss[i].b);
    61         ans += pluss[i].co;
    62     }
    63     for(int i = 1;i <= now2;++i){
    64         sum = min(sum,ans - dece[i].b);
    65         ans += dece[i].co;
    66     }
    67     printf("%lld
    ",abs(sum));
    68     return 0;
    69 }

    如果大家对我的博客有所意见,请通过我的邮箱联系我,谢谢。

  • 相关阅读:
    【Java并发编程】之十一:线程间通信中notify通知的遗漏
    【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明
    【Java并发编程】之九:死锁
    【Java并发编程】之八:多线程环境中安全使用集合API
    【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
    多线程开发中遇到的问题
    Linux 设置IP,gate, 以及自动获取IP的方法
    C语言实现http get请求程序
    DHCP(动态主机配置协议)工作流程
    多线程程序中死锁的分析和解决方案
  • 原文地址:https://www.cnblogs.com/gangding/p/5705400.html
Copyright © 2020-2023  润新知