[bzoj4977]跳伞求生<贪心>

beat365下载地址 ⌚ 2025-07-20 09:11:20 👤 admin 👁️ 8491 ❤️ 235
[bzoj4977]跳伞求生<贪心>

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4977

这是八月月赛的一道题,月赛的时候和同学讨论了一下,最后由一位叫二哥的大佬率先AC,用的是贪心(学不来学不来),虽然正解貌似是dp(不清楚);

看了看这道题的数据范围,我并没有打算怎么去优化,直接暴力的处理加上贪心操作,我一开始用的是优先队列,结果数据一大结果就是负数(还有这操作???),后来我把优先队列改成了几个数组,然后多次快排(毕竟数据范围不大),终于AC了;

这个贪心用到了一个结论,就是在确定的敌人和队友之间,交换彼此的对手,总值不变,意思是:

原本的配对方案是队友1打敌人1,队友2打敌人3,然后假如队友1,2交换,总值不变,用式子来说就是:

ans=(a1-b1+c1)+(a2-b2+c2)=(a2-b1+c1)+(a1-b2+c2);

具体步骤是:

1.首先存下ci-bi的值val,然后按照val从大到小排序,并让ai按照从大到小排序,同时开一个桶(本人的方法,没有优化,听起来可能比较复杂)

2.然后按val大小找,如果当前敌人可以被打死,那就意味这我们需要一个我方队友,tot++(建议这时候找刚刚比b大的a)

3.然后找前tot大的人作为我方人员,与敌方参战的tot人配对,这时候我开了两个数组,分别存,我方参战和敌方参战人员,并按从小到大排序

4.接着会用到我们的结论(即上文红字),所以我们要删除人,我们把我方ai最小和敌人val(ci-bi)最小的相加,如果为负就删除,不然留下他们就是负贡献(至于为什么删和为什么可以删掉,想想结论,并假设3步骤选出来的人就固定且选出来的每个队友都可以打一个任意选出来的敌人)

5.最后把留下的贡献为正的相加即可

代码我先给一个优先队列的,可以A一部分(并没有什么卵用),但是希望大佬能为我解释一下,为什么数据大了就会成负的?

第一个代码是不能AC的代码!!

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #define maxn 100005

10 using namespace std;

11

12 struct node{

13 int b,c,val;

14 }e[maxn];

15

16 int comp(const void*a,const void*d)

17 {

18 if((*(struct node*)a).val==(*(struct node*)d).val)

19 return (*(struct node*)a).b>(*(struct node*)d).b?1:-1;

20 return (*(struct node*)a).val>(*(struct node*)d).val?-1:1;

21 }

22

23 int n,m,gun[maxn],maxx;

24 long long sc;

25

26 priority_queueq;

27 priority_queue,greater >q1;

28 priority_queue,greater >q2;

29

30 int main()

31 {

32 scanf("%d%d",&n,&m);

33 for(int i=1;i<=n;i++)

34 {

35 int x;

36 scanf("%d",&x);

37 maxx=max(maxx,x);

38 //if(gun[x]==0)q.push(x);

39 q.push(x);

40 gun[x]++;//一个桶来存各种子弹人数,每次选距离消耗最近的

41 }

42 for(int i=1;i<=m;i++)

43 {

44 int x,y;

45 scanf("%d%d",&x,&y);

46 e[i].b=x;e[i].c=y;

47 e[i].val=y-x;

48 }

49 e[0].b=0x3f3f3f;e[0].val=0x3f3f3f;

50 qsort(e,m+1,sizeof(e[0]),comp);

51 int tot=0;

52 for(int i=1;i<=m;i++)

53 {

54 if(e[i].b

55 for(int j=e[i].b+1;j<=maxx;j++)

56 {

57 if(gun[j]>0)

58 {

59 gun[j]--;

60 tot++;

61 q2.push(e[i].val);

62 break;

63 }

64

65 }

66 }

67

68 }

69 for(int i=1;i<=tot;i++)

70 {

71 int dd=q.top();

72 q1.push(q.top());

73 q.pop();

74 }

75 for(int i=1;i<=tot;i++)

76 {

77 int x,y;

78 x=q1.top();y=q2.top();

79 if(x+y<=0){

80 q1.pop();q2.pop();

81 }

82 else break;

83 }

84 int yy=q1.size();

85 for(int i=1;i<=yy;i++)

86 {

87 sc+=q1.top()+q2.top();

88 q1.pop();q2.pop();

89 }

90 printf("%lld",sc);

91 }

92

View Code

接下来是用数组和快排代替优先队列的(排版较暴力)

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #define maxn 100005

10 using namespace std;

11

12 struct node{

13 int b,c,val;

14 }e[maxn];

15

16 int comp(const void*a,const void*d)

17 {

18 if((*(struct node*)a).val==(*(struct node*)d).val)

19 return (*(struct node*)a).b>(*(struct node*)d).b?1:-1;

20 return (*(struct node*)a).val>(*(struct node*)d).val?-1:1;

21 }

22

23 int cmp1(const void*a,const void*d)

24 {

25 return (*(int*)a)>(*(int*)d)?-1:1;

26 }//从大到小

27

28 int cmp2(const void*a,const void*d)

29 {

30 return (*(int*)a)>(*(int*)d)?1:-1;

31 }//从小到大

32

33 int n,m,gun[maxn],maxx,num[maxn],nu[maxn];

34 long long sc;

35

36 int main()

37 {

38 /* freopen("in.in","r",stdin);

39 freopen("my.out","w",stdout);*/

40 scanf("%d%d",&n,&m);

41 for(int i=1;i<=n;i++)

42 {

43 int x;

44 scanf("%d",&x);

45 maxx=max(maxx,x);

46 num[i]=x;

47 gun[x]++;//一个桶来存各种子弹人数,每次选距离消耗最近的

48 }

49 num[0]=0x3f3f3f;

50 qsort(num,n+1,sizeof(int),cmp1);

51 for(int i=1;i<=m;i++)

52 {

53 int x,y;

54 scanf("%d%d",&x,&y);

55 e[i].b=x;e[i].c=y;

56 e[i].val=y-x;

57 }

58 e[0].b=0x3f3f3f;e[0].val=0x3f3f3f;

59 qsort(e,m+1,sizeof(e[0]),comp);

60 int tot=0;

61 for(int i=1;i<=m;i++)

62 {

63 if(e[i].b

64 for(int j=e[i].b+1;j<=maxx;j++)

65 {

66 if(gun[j]>0)

67 {

68 gun[j]--;

69 tot++;

70 nu[tot]=e[i].val;

71 break;

72 }

73

74 }

75 }

76

77 }

78 num[0]=nu[0]=-0x3f3f3f;

79 qsort(num,tot+1,sizeof(int),cmp2);

80 qsort(nu ,tot+1,sizeof(int),cmp2);

81 for(int i=1;i<=tot;i++)

82 {

83 if(num[i]+nu[i]<=0)

84 {

85 continue;

86 }else{

87 sc+=num[i]+nu[i];

88 }

89 }

90 printf("%lld",sc);

91

92 }

93

View Code

相关数据

创维电视怎么样?十年铁粉告诉你创维电视值得购买

创维电视怎么样?十年铁粉告诉你创维电视值得购买

对于一个家庭来说,电视是必不可少的一个生活电器。虽然说手机改变生活,现在大家看电视的时间也越来越少,但是在逢年过节、家庭聚会电

07-11 体育投注英超和欧冠
牛叉帮助

牛叉帮助

数据下载及管理 数据下载及管理:提供数据下载功能,便于提高选股、区间统计等功能的准确性。 1、“盘后数据下载” 对于因为某些原因而不

07-18 365体育欧洲版本
世界杯-博格巴+姆巴佩破门 法国4-2克罗地亚夺冠

世界杯-博格巴+姆巴佩破门 法国4-2克罗地亚夺冠

博格巴庆祝进球 北京时间7月15日23时(俄罗斯当地时间18时),第21届世界杯决赛在莫斯科卢日尼基球场打响,法国4比2击败克罗地亚,第2次夺得

07-12 体育投注英超和欧冠
駭的组词

駭的组词

駭的组词 駭字的常见组词有:獸駭、駭詫、駭竄、驚心駭矚、駭亂、駭異、駭觀、振駭、變駭、魚駭、諠駭、蟻潰鼠駭、懾駭、碭駭、騷駭、駭

07-09 365体育欧洲版本
火车票靠窗的位置是多少号?火车靠窗的座位号有哪些

火车票靠窗的位置是多少号?火车靠窗的座位号有哪些

火车票分为软座或硬座,火车票硬座的靠窗位置为尾数为“0”、“4”、“5”、“9”的号码(前提是该车厢定员为118人),尾数为“3”、“4”

07-16 beat365下载地址
二月开的花有哪些?它们各自寓意着什么?

二月开的花有哪些?它们各自寓意着什么?

二月是春节过后不久的时节,在这个春寒料峭的月份里,一些植物开始迎春绽放。在中国传统文化中,花开常常寓含着各种美好的寓意和象征。

07-01 365体育欧洲版本