#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <queue>
using namespace std;
//pomysl: najpierw odwiedzamy wszystkie potwory z dodatnim saldem, bo po nich mamy wiecej zycia
// potem z ujemnym, ale idziemy od konca. Walczymy ze wszystkimi, wiec wiemy, ile dokladnie na koniec
// bedziemy miec zycia. Teraz 'cofamy sie' i wybieramy potwora z eliksirem mniejszym od ilosci zycia, ktora nam pozostala
// (bo przed wypiciem musial miec zycie >=0) oraz takiego, ktory jednoczesnie ma najmniejsze saldo (najwiecej traci)
//(bo chcemy jak najdluzej miec jak najwiecej zycia)
int main() {
int n;
int a;
scanf("%d%d",&n,&a);
long long int life = a;
long long int endLife = life; //ile zycia bedziemy miec na koniec
int monster[n]; //ile zycia zabierze nam potwor
int eliksir[n]; //ile zycia odzyskamy po walce
vector< pair<int,int> > good; //lista par ile zabierze potwor + nr potwora dla tych potorow, dla ktorych po walce mamy wiecej zycia
vector< pair<int,int> > bad; //lista par ile da eliksir + nr potwora dla tych potworow, dla ktorych po walce mamy mniej zycia (lub rowno)
priority_queue< pair<int,int> > q; //kolejka z priorytetem bedacym saldem, druga wartosci to nr potwora
for (int i=0; i<n; i++)
{
scanf("%d%d", &monster[i], &eliksir[i]);
endLife = endLife - monster[i] + eliksir[i];
if (eliksir[i] - monster[i] > 0) //dodatnie saldo walki
{
pair<int,int> p;
p.first = monster[i];
p.second = i;
good.push_back(p);
}
else //ujemne saldo walki
{
pair<int,int> p;
p.first = eliksir[i];
p.second = i;
bad.push_back(p);
}
}
if (endLife <= 0)
{
printf("NIE\n");
return 0;
}
sort(good.begin(), good.end());
sort(bad.begin(), bad.end());
vector<int> result;
vector<int> resultReverse; //czesc rozwiazania zawierajaca potwory z ujemnym saldem (odwrocona)
bool isOK = true;
//wypelnianie wynikow potworami z dodatnim saldem
for (int i=0; i<good.size(); i++)
{
if (life > good[i].first)
{
life = life - monster[good[i].second] + eliksir[good[i].second];
result.push_back(good[i].second);
}
else
{
isOK = false;
break;
}
}
if (!isOK)
{
printf("NIE\n");
return 0;
}
//wypelnianie wyniku potworami z ujemnym saldem
int i=0;
while (resultReverse.size() != bad.size())
{
while (i < bad.size() && endLife > bad[i].first)
{
pair<int, int> p;
p.first = monster[bad[i].second]-eliksir[bad[i].second];
p.second = bad[i].second;
q.push(p);
i++;
}
if (q.empty())
{
isOK = false;
break;
}
pair<int,int> best = q.top();
q.pop();
endLife = endLife + best.first;
resultReverse.push_back(best.second);
}
if (!isOK)
printf("NIE\n");
else
{
printf("TAK\n");
for (int i=0; i<result.size(); i++)
printf("%d ",result[i]+1);
for (int i=resultReverse.size()-1; i>=0; i--)
printf("%d ",resultReverse[i]+1);
printf("\n");
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #include <iostream> #include <vector> #include <algorithm> #include <stdio.h> #include <queue> using namespace std; //pomysl: najpierw odwiedzamy wszystkie potwory z dodatnim saldem, bo po nich mamy wiecej zycia // potem z ujemnym, ale idziemy od konca. Walczymy ze wszystkimi, wiec wiemy, ile dokladnie na koniec // bedziemy miec zycia. Teraz 'cofamy sie' i wybieramy potwora z eliksirem mniejszym od ilosci zycia, ktora nam pozostala // (bo przed wypiciem musial miec zycie >=0) oraz takiego, ktory jednoczesnie ma najmniejsze saldo (najwiecej traci) //(bo chcemy jak najdluzej miec jak najwiecej zycia) int main() { int n; int a; scanf("%d%d",&n,&a); long long int life = a; long long int endLife = life; //ile zycia bedziemy miec na koniec int monster[n]; //ile zycia zabierze nam potwor int eliksir[n]; //ile zycia odzyskamy po walce vector< pair<int,int> > good; //lista par ile zabierze potwor + nr potwora dla tych potorow, dla ktorych po walce mamy wiecej zycia vector< pair<int,int> > bad; //lista par ile da eliksir + nr potwora dla tych potworow, dla ktorych po walce mamy mniej zycia (lub rowno) priority_queue< pair<int,int> > q; //kolejka z priorytetem bedacym saldem, druga wartosci to nr potwora for (int i=0; i<n; i++) { scanf("%d%d", &monster[i], &eliksir[i]); endLife = endLife - monster[i] + eliksir[i]; if (eliksir[i] - monster[i] > 0) //dodatnie saldo walki { pair<int,int> p; p.first = monster[i]; p.second = i; good.push_back(p); } else //ujemne saldo walki { pair<int,int> p; p.first = eliksir[i]; p.second = i; bad.push_back(p); } } if (endLife <= 0) { printf("NIE\n"); return 0; } sort(good.begin(), good.end()); sort(bad.begin(), bad.end()); vector<int> result; vector<int> resultReverse; //czesc rozwiazania zawierajaca potwory z ujemnym saldem (odwrocona) bool isOK = true; //wypelnianie wynikow potworami z dodatnim saldem for (int i=0; i<good.size(); i++) { if (life > good[i].first) { life = life - monster[good[i].second] + eliksir[good[i].second]; result.push_back(good[i].second); } else { isOK = false; break; } } if (!isOK) { printf("NIE\n"); return 0; } //wypelnianie wyniku potworami z ujemnym saldem int i=0; while (resultReverse.size() != bad.size()) { while (i < bad.size() && endLife > bad[i].first) { pair<int, int> p; p.first = monster[bad[i].second]-eliksir[bad[i].second]; p.second = bad[i].second; q.push(p); i++; } if (q.empty()) { isOK = false; break; } pair<int,int> best = q.top(); q.pop(); endLife = endLife + best.first; resultReverse.push_back(best.second); } if (!isOK) printf("NIE\n"); else { printf("TAK\n"); for (int i=0; i<result.size(); i++) printf("%d ",result[i]+1); for (int i=resultReverse.size()-1; i>=0; i--) printf("%d ",resultReverse[i]+1); printf("\n"); } } |
English