[BZOJ3709]&&[PA2014]Bohater

描述 Description

在一款电脑游戏中,你需要打败 n 只怪物(从 1 到 n 编号)。为了打败第 i 只怪物,你需要消耗 d[i] 点生命值,但怪物死后会掉落血药,使你恢复 a[i] 点生命值。任何时候你的生命值都不能降到 0(或 0 以下)。请问是否存在一种打怪顺序,使得你可以打完这 n 只怪物而不死掉。

输入格式 InputFormat

第一行两个整数 n,z(1<=n,z<=100000),分别表示怪物的数量和你的初始生命值。

接下来 n 行,每行两个整数 d[i],ai

输出格式 OutputFormat

第一行为 TAK(是)或 NIE(否),表示是否存在这样的顺序。

如果第一行为 TAK,则第二行为空格隔开的 1~n 的排列,表示合法的顺序。如果答案有很多,你可以输出其中任意一个。

样例输入 SampleInput

3 5
3 1
4 8
8 3

样例输出 SampleOutput

TAK
2 3 1


BZOJ 3709


代码 Code

先打不会让自己掉血的怪,比如按照 d 值升序打;接着打剩下的怪,因为如果能够都打完的话会发现其实是将 a 和 d 值反过来看,即按照 a 的降序打怪。

好像没有 special judge…

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int i,j,t,n,m,l,r,k;
struct monster
{
    int d,a,id;
}ma[100005],mb[100005];
int sa,sb;
long long z,y,x;
inline bool compa(monster a,monster b)
{
    return a.d<b.d;
}
inline bool compb(monster a,monster b)
{
    return a.a>b.a;
}
inline bool kill(monster* s,int ss)
{
    int i,j,t;
    for (i=1;i<=ss;i++)
    {
        if (z<=s[i].d)
        {
            printf("NIE\n");
            return false;
        }
        z+=s[i].a-s[i].d;
    }
    return true;
}
int main()
{
    sa=sb=0;
    scanf("%d%lld",&n,&z);
    for (i=1;i<=n;i++)
    {
        scanf("%lld%lld",&x,&y);
        if (x<=y) 
        {
            ma[++sa].d=x;ma[sa].a=y;ma[sa].id=i;
        }
        else
        {
            mb[++sb].d=x;mb[sb].a=y;mb[sb].id=i;
        }
    }
    sort(ma+1,ma+sa+1,compa);
    sort(mb+1,mb+sb+1,compb);
    if (!kill(ma,sa)) return 0;
    if (!kill(mb,sb)) return 0;
    printf("TAK\n");
    for (i=1;i<=sa;i++) printf("%d",ma[i].id);
    for (i=1;i<=sb;i++) printf("%d",mb[i].id);
    return 0;
}