JZOJ-senior-5937. 【NOIP2018模拟10.30】斩杀计划

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/83686109

Time Limits: 1000 ms Memory Limits: 262144 KB

Description

众所周知,小J和小G是死对头,一天小G带领一群小弟找到了小J。

小G有n个小弟,第i个小弟有ai点攻击力,小G有m点血量。
小J在小G找小第的时间里去找小Z学到了膜法,他在大战前配置了三种魔法药水

1:复用型药水:花费1法力值,选择小G的攻击力小于等于2的一个小弟让他跟随自己(变为自己的小弟并且攻击力和属于小G时一样)

2:猎人药水:花费4法力值,选择小G的攻击力小于等于3的一个小弟让他跟随自己

3:腐败药水:花费1法力值,使小G所有小弟攻击力降低三点(使用前两种魔法将小弟拉到自己阵营时小弟攻击力就是当前的攻击力,即小J的小弟攻击力只能为1,2,3)

为了向小G展现自己的力量,他打算在召集到一些小弟后发动攻击(每个小弟打一次)直接秒杀小G(攻击力大于等于m)

由于智商有限,小J在配置腐败药水时会花费很大精力,他需要知道自己最少使用多少腐败药水,并在腐败药水数量最小的情况下花费最小的法力值

Input

第一行两个正整数n,m表示小G的小弟数量和血量
第二行n个正整数表示小G所有小弟的攻击力

Output

一行两个整数表示最小的腐败药水数量和在腐败药水最小的情况下法力值花费,如果无论如何都无法战胜,输出一个整数-1

Sample Input

Sample Input1:
3 5
1 2 3

Sample Input2:
8 8
10 20 30 40 50 60 70 80

Sample Input3:
8 80
10 20 30 40 50 60 70 80

Sample Output

Sample Output1:
0 5

样例说明
对2,3小弟使用复用型药水和猎人药水

Sample Output2:
16 23

样例说明
使用16个腐败药水
在第3个腐败药水时拉10,攻击力为1
在第6个腐败药水时拉20,攻击力为2
在第9个腐败药水时拉30,攻击力为3
在第16个腐败药水时拉50,攻击力为2

Sample Output3:
-1

Data Constraint

数据规模和约定
测试点1,2: n≤10并且最优情况不需要使用腐败药水和猎人药水
测试点3,4: n≤10并且最有情况不需要使用腐败药水
测试点5,6,7: n≤10
测试点8,9,10: n≤5000000,最大攻击力小于等于30000
对于所有数据 0≤m≤5000000

Hint

​提示
鉴于本题为签到题直接输出-1或者0,0都能获得10分的好成绩
请仔细阅读题目,有些细节可能让你损失很多的分数0.0
输入规模较大,请使用较快的读入方式

Solution

  • 输入时记录下有每个小弟需要用药水的次数以及最终攻击力
  • 二分求出使用腐败药水的最少次数
  • 使得在这个次数内能拉过来的小弟的总攻击力大于 m m
  • 最后贪心地删去多余的小弟
  • 优先删去3(花费4,不值),然后删去 1(相同代价下攻击力较小),最后删去 2

Code

#include<algorithm>
#include<cstdio>
#include<cctype>

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)

using namespace std;

const int M=1e4+5;
int n,m,x,mx,mag,s[M],a[M][4];

inline void read(int &n)
{
	int x=0,w=0; char ch=0;
	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	n=w?-x:x;
}

void get_magic(int cs)
{
	int more=s[cs]-m;
	mag=a[cs][1]+a[cs][2]+4*a[cs][3];
	if(a[cs][3])
	{
		int k=min(more/3,a[cs][3]);
		more-=3*k,mag-=4*k;
	}
	if(a[cs][1])
	{
		int k=min(more,a[cs][1]);
		more-=k,mag-=k;	
	}
	if(a[cs][2])
	{
		int k=min(more/2,a[cs][2]);
		more-=2*k,mag-=k;
	}
}

int main()
{
	freopen("zhanshajihua.in","r",stdin);
	freopen("zhanshajihua.out","w",stdout);
	read(n),read(m),mx=0;
	fo(i,1,n)
	{
		read(x);
		if(!x) continue;
		int p=(x-1)/3; x-=3*p;
		int q=x<=2?1:4; mx=max(p,mx);
		s[p]+=x,++a[p][x];
	}

	fo(i,1,mx)
	{
		s[i]+=s[i-1];
		a[i][1]+=a[i-1][1];
		a[i][2]+=a[i-1][2];
		a[i][3]+=a[i-1][3];
	}
	
	int l=0,r=mx+1;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(s[mid]>=m) r=mid;
			else l=mid+1;
	}
	
	if(l==mx+1) {printf("-1"); return 0;}
	get_magic(l);
	printf("%d %d",l,mag+l);
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/83686109