这是2014年上海区域赛的一道水题。请原谅我现在才发出来,因为我是在太懒了。当然,主要原因是我刚刚做出来。

其实去年我就已经看到这道题了,因为我参加的就是那一场。但是当时我们爆零,伤心的我就再也没有看过那一场的题了。昨天我的队友的高中同学建议我们一起来打一打这场比赛吧,然后我才再次回顾这场比赛。结果一堆琐事,我一共也没有做多久的题,我的队友扎扎实实看了5个小时的题,把另一道水题给过了。全场我们也只过了那么一道题。学姐说,做重现赛和现场赛比较,需要去掉一题,那么我们又爆零了。

题意:

我方有n个人,敌方有m个人。每个人有攻击力a,防御力d。如果我方的人i攻击力比敌方的人j的防御力高,那么i可以杀死j,否则杀不死。当然,如果同时j的攻击力比i个防御力高,那么j同时会杀死i。

但是,每个人只能打一次,无论存活下来还是死去。

求我方在杀死所有敌人的情况下,最多可以留下多少人?

输入:

首行一个整型t,表示共有t组数据。

接下来,每组数据首行两个整型n,m,分别表示我方人数和敌方人数。

接下来n行,每行两个整型a,d,表示我方某人的攻击力与防守力。

接下来m行,每行两个整型a,d,表示敌方某人的攻击力与防守力。

输出:

首先输出”Case #x: ”,x是数据组数。

如果无法杀死敌方所有人,那么输出-1。否则输出我方幸存人数。

题解:

去年的时候这道题我是一点思路也没有,今年有了一点思路,然后顺利的tle了好几发。实际上我距离正确结果只差一步了,但是这一步就是咫尺天涯。

1. 输入的时候我把敌人的攻击和防守反转一下输入,己方的正常输入。

2. 我要把所有人都放在一起,按照攻击a从大到小排序。初始化ans = n;

3. 所有人从大到小读取,直到读取到一个敌人为止。这样,我可以保证,我所有的读取到的我方的人都可以杀死当前的敌人,因为敌人的防守力参与了我方的攻击力的排序。

4. 我要迅速的从我方已经读取的人中寻找一个既可以杀死敌人,又尽可能保存自己的人。即,将我方以读取的人按照防御从小到大排序,找到一个恰好可以防住当前敌人的人。然后将这个人从读取的己方人中删除。表示他杀掉了一个敌人,完成使命。当我方所有人都无法防住敌人的攻击,那就选一个防守最低的人来杀敌,同时也被杀,ans--; 继续读取数组。即,进行步骤3。

5. 当所有的敌人都被杀死时,输出结果。当遇到敌人但无人能杀掉他时,中断读取,输出-1。

写到这里可能有人会有疑问了——

  1. 为什么在寻找人时可以重新排序(将排好的序打乱)呢?

因为我们只需要保证我们的人能够杀死敌人当前的人就行了。

所以,我们先按照我方的攻击从大到小找人,敌人的防守从大到小找人。这样,我们已经找到的我方的人只要能够杀死当前的敌人,那么就肯定能杀死后面的敌人。那么我们找到的我方的人无论怎么打乱顺序都无所谓了,反正肯定都能杀死敌人。此时的攻击力的顺序已经没有意义了。

  1. 为什么从可以杀死敌人的我方人中选取刚好能够防住的,如果防不住则选取防最低的,而不直接选取防守最高的呢?

因为,我们是按照我方攻击和敌方防守排的序,所以,无法保证后面防守低的敌人攻击也低。如果我们当前有两个人——

攻击为10,防守为10;

攻击为10,防守为5;

先找到一个敌人——攻击为1,防守为6。那么如果用攻击为10,防守为10的我方士兵。那么如果下一个敌人是攻击为6,防守为1呢?如果用攻击为20,防守为5的,则我方会死一个人。而反过来就都能存活。

如果敌人第一个攻击为11,防守为6,那么如果先用防守高的,则我方会死一个人   下一个敌人攻击为6,防守为6,我方又会死一个人。而反过来只会死一个人。

在保证能够杀死敌人的情况下,优先使用防守低的人,保留防守高的人,能活则活,不能活的就给个死的最痛快的。

然后我就如何将我方的人按照防守力进行第二次排序进行了“深入细致”的思考,结果得到的结论是——使用最快的排序!即k*log2(k)!k表示当前满足条件的我方的人数。哦,我真是SB了!这样一来,我进行了m次排序,且排序长度最差情况是k == n一直到k == n-m+1。可以达到n*n*log2(n)。我不超时谁超时?

后来看了题解,发现,可以用set来保存啊,这样就不需要每次都排一次序了,添加我方第k个人时时间复杂度是log2(k),很稳定,小于n*log2(n)。

我真是脑残了。明明都想到了可以如果把排序降到log2(n)的话一定能过,为什么就是想不到set每次操作是log2(n)呢?涨涨记性,嗯,一定要涨涨记性。

当然,这道题因为会出现重复数据,那么需要用multiset,当然,使用方法大同小异。

还有一点,学会了使用stl的upper_bound()函数。返回值和参数都是一个当前容器的格式。

ps. 当然代码和思路还有些区别,但区别不大。

pss. 头一次写这么长的题解,赶上总结了……

上代码——

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <algorithm>
  4. #include <set>
  5. using namespace std;
  6.  
  7. const int N = ;
  8.  
  9. struct Node
  10. {
  11. int a, d;
  12. int id;
  13. }s1[N], s2[N];
  14.  
  15. int n, m, t;
  16. int ans;
  17.  
  18. bool cmp(Node x, Node y)
  19. {
  20. return x.a > y.a;
  21. }
  22.  
  23. void Init()
  24. {
  25. scanf("%d%d", &n, &m);
  26. for(int i = ; i < n; i++)
  27. {
  28. scanf("%d%d", &s1[i].a, &s1[i].d);
  29. s1[i].id = ;
  30. }
  31. for(int i = ; i < m; i++)
  32. {
  33. scanf("%d%d", &s2[i].d, &s2[i].a);
  34. s2[i].id = ;
  35. }
  36. sort(s1, s1+n, cmp);
  37. sort(s2, s2+m, cmp);
  38. ans = n;
  39. }
  40.  
  41. void Work()
  42. {
  43. multiset <int> st;
  44. st.clear();
  45. for(int i = , j = ; j < m; j++)
  46. {
  47. while(s2[j].a <= s1[i].a && i < n)
  48. {
  49. st.insert(s1[i].d);
  50. i++;
  51. }
  52. if(st.empty()) {ans = -; return;}
  53. multiset<int>::iterator mid = st.upper_bound(s2[j].d);
  54. if(mid == st.end())
  55. {
  56. st.erase(st.begin());
  57. ans--;
  58. }
  59. else st.erase(mid);
  60. }
  61. }
  62.  
  63. int main()
  64. {
  65. //freopen("test.in", "r", stdin);
  66. scanf("%d", &t);
  67. for(int tm = ; tm <= t; tm++)
  68. {
  69. Init();
  70. Work();
  71. printf("Case #%d: %d\n", tm, ans);
  72. }
  73. }

UVALive 7146 (贪心+少许数据结构基础)2014acm/icpc区域赛上海站的更多相关文章

  1. 近几年ACM/ICPC区域赛铜牌题

    2013 changsha zoj 3726 3728 3736 3735 2013 chengdu hud 4786 4788 4790 2013 hangzhou hdu 4770 4771 47 ...

  2. 2019年icpc区域赛银川站总结

    目录 一.前言 二.10月19日热身赛 三.10月20日正式赛 四.结果 一.前言 比赛前我们队有ccpc厦门和icpc银川的名额,然而这两个地区的时间正好撞了,考虑到银川更容易拿奖,加上我们ACM协 ...

  3. 2017 ICPC区域赛(西安站)--- J题 LOL(DP)

    题目链接 problem description 5 friends play LOL together . Every one should BAN one character and PICK o ...

  4. 2018 ICPC 区域赛 焦作场 D. Keiichi Tsuchiya the Drift King(计算几何)

    http://codeforces.com/gym/102028/problem/D 题意:根据题中给的那个图,然后题目给你 a,b,r,d,让你求出最小的满足矩形通过弯道的w 思路:

  5. 2018 青岛ICPC区域赛E ZOJ 4062 Plants vs. Zombie(二分答案)

    Plants vs. Zombies Time Limit: 2 Seconds      Memory Limit: 65536 KB BaoBao and DreamGrid are playin ...

  6. 2014acm亚洲区域赛陕西赛总结

    这次是第一次出来到外面比赛,一切都是非常新鲜的,带着新鲜来到了古城西安.首先感觉就是志愿者一点都不热情.一副爱理不理的,这不是有违我大西北人的热情好客么. 直接说比赛吧. 第一天热身赛,出了两道非常水 ...

  7. 2016 ACM/ICPC 区域赛(北京) E 题 bfs

    https://vjudge.net/problem/UVALive-7672 题意    输入一个五位数n 问由12345变到n的操作最少次数 不可达输出-1 有三种操作 1.交换相邻的位置 次数不 ...

  8. 算法与数据结构基础 - 贪心(Greedy)

    贪心基础 贪心(Greedy)常用于解决最优问题,以期通过某种策略获得一系列局部最优解.从而求得整体最优解. 贪心从局部最优角度考虑,只适用于具备无后效性的问题,即某个状态以前的过程不影响以后的状态. ...

  9. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

随机推荐

  1. python---redis管道(事务)和发布订阅

    管道:将数据操作放在内存中,只有成功后,才会一次性全部放入redis #管道(事务),要是都成功则成功,失败一个全部失败 #原理:将数据操作放在内存中,只有成功后,才会一次性全部放入redis pip ...

  2. linux系统root密码忘了怎么办 三种方法快速找回root密码

    linux root密码找回方法一 第1步:在系统进入单用户状态,直接用passwd root去更改. 第2步:用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法如下: ...

  3. CM记录-HDFS清理垃圾回收站

    HDFS数据块所在存储的目录满了的解决方法 1.增加磁盘空间 2.删除回收站 hadoop dfs -du -h 查看各个HDFS空间占用情况 hadoop dfs  -expunge  清空回收站 ...

  4. bzoj千题计划207:bzoj1879: [Sdoi2009]Bill的挑战

    http://www.lydsy.com/JudgeOnline/problem.php?id=1879 f[i][j] 表示匹配了i个字符,匹配字符串的状态为j的方案数 枚举下一个字符是什么 计算加 ...

  5. python学习笔记6--操作Mysql

    一.mysql操作 import pymysql #连上mysql ip 端口号 密码 账号 数据库 #建立游标 #执行sql #获取结果 #关闭连接.关闭游标 conn=pymysql.connec ...

  6. .NET面试题系列(九)C# 结构体与类的区别

    谈一下什么时候使用结构,什么使用类. 我们知道,结构存储在栈中,而栈有1个特点,就是空间较小,但是访问速度较快,堆空间较大,但是访问速度相对较慢.所以当我们描述1个轻量级对象的时候,可以将其定义为结构 ...

  7. 通过vnc访问无显卡服务器的图形环境

    最近在一台没有显卡的 Power 服务器上,安装了Fedora 22,因为没有显卡,所以不能在本机启动Xserver,于是想通过vnc的方式远程访问服务器的图形环境. 在服务器上安装好xserver和 ...

  8. Convert Expression to Reverse Polish Notation

    Given an expression string array, return the Reverse Polish notation of this expression. (remove the ...

  9. Linux 定时器应用【转】

    Linux 定时器应用 实验目的 阅读 Linux 相关源代码,学习 Linux 系统中的时钟和定时器原理,即,ITIMER_REAL实时计数,ITIMER_VIRTUAL 统计进程在用户模式执行的时 ...

  10. Linux 串口、usb转串口驱动分析(2-1) 【转】

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26807463&id=4186851 Linux 串口.usb转 ...