题解 P4025 [PA2014]Bohater
题目中没有说怪物掉落的血药 和消耗的生命值 的大小关系,所以我们可以把怪物分为两类:补血怪()与掉血怪()。
容易发现的是,一定是先打完补血怪再打掉血怪。因为打掉血怪没有益处,反而减少生命值。所以我们把它分为两部分,第一部分是打补血怪,第二部分是打掉血怪。
第一部分,在打每个补血怪时的要求是 。由于 会逐渐变大,所以应当先打 小的怪物。
第二部分,在打每个掉血怪时的要求是 。但是 会逐渐变小,我们不能先打 小/大的怪物。怎么办?我们考虑倒序,计算打完所有怪物后的剩余生命值,从最后开始考虑。每一个怪物相当于让 先减去 再加上 。条件变成了 。由于是倒序, 会逐渐增大,所以倒序按 从小到大打就行了。调整回正序就是按照 从大到小。
以下是部分代码(几乎全部)。
#define ll long long
const int N=100005;
ll n,z;
struct mon
{
ll d,a;
int id;
}a[N],b[N],c;
int cnta,cntb;
bool cmp1(mon x,mon y)
{
return x.a<y.a;
}
bool cmp2(mon x,mon y)
{
return x.d<y.d;
}
int main()
{
n=read(),z=read();
ll p=z;
for (int i=1;i<=n;i++)
{
c.d=read(),c.a=read(),c.id=i;
if (c.d>c.a) b[++cntb]=c;
else a[++cnta]=c;
z-=c.d,z+=c.a;
}
sort(a+1,a+cnta+1,cmp2);
sort(b+1,b+cntb+1,cmp1);
for (int i=1;i<=cntb;i++)
{
if (z>b[i].a) z+=b[i].d-b[i].a;
else
{
puts("NIE");
return 0;
}
}
z=p;
for (int i=1;i<=cnta;i++)
{
if (z>a[i].d) z+=-a[i].d+a[i].a;
else
{
puts("NIE");
return 0;
}
}
puts("TAK");
for (int i=1;i<=cnta;i++) cout << a[i].id << " ";
for (int i=cntb;i>=1;i--) cout << b[i].id << " ";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?