Ice-cream Tycoon
Problem Description
You’ve recently started an ice-cream business in a local school. During a day you have many suppliers delivering the ice-cream for you, and many students buying it from you. You are not allowed to set the prices, as you are told the price for each piece of ice-cream by the suppliers.
The day is described with a sequence of queries. Each query can be either ARRIVE n c, meaning that a supplier has delivered n pieces of ice-cream priced c each to you, or BUY n t, meaning that a student wants to buy n pieces of ice-cream, having a total of t money. The latter is processed as follows: in case n cheapest pieces of ice-cream you have cost no more than t (together), you sell those n cheapest pieces to the student; in case they cost more, she gets nothing. You start the day with no ice-cream.
For each student, output HAPPY if she gets her ice-cream, and UNHAPPYif she doesn’t.
Input
The input file contains between 1 and 105 queries (inclusive), each on a separate line. The queries are formatted as described above, either ARRIVE n c or BUY n t, 1 ≤ n, c ≤ 106, 1 ≤ t ≤ 1012.
Output
For each BUY-query output one line, containing either the word HAPPY or the word UNHAPPY (answers should be in the same order as the corresponding queries).
Sample Input
ARRIVE 1 1
ARRIVE 10 200
BUY 5 900
BUY 5 900
BUY 5 1000
Sample Output
HAPPY
UNHAPPY
HAPPY
题意
有一个冰激凌店,冰激凌店的物品价格无法自由定价,有两种事件:
- 进货 ,有n个冰激凌到达店里,每个进价为c
- 售卖,有人来买n个冰激凌,共付t元,店员会把n个进价最便宜的冰激凌拿出来,如果进价总和超过t元,则不售卖,否则就卖给他。
求每个购买冰激凌的人能否买到自己需要的冰激凌。
题解:
题目的两种操作,主要有查询和更改两种操作,需要快速计算出最小的n个物品的权值和。可以利用线段树或平衡树来维护。对于更新操作,直接插入即可,物品售出后,n个物品的删除操作,可以按价格删除,每次删除价格最少的物品,这样最多把加入进来的物品全部删除,复杂度是可以接受的。
使用线段树可以先读入所有输入,然后对数据离散化,线段树维护区间和 、 物品数量。 (PS:其实不离散化也是可以的,毕竟价格最高1e6)。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<queue>
#include<stack>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<LL, int> P;
const int maxn = 1000100;
const int mod = 1000000007;
LL sum[maxn*3], a[maxn], p[maxn*3];
void creat(int l, int r, int k);
LL queryid(int l, int r, int k);
LL querysum(int l, int r, int x, int k);
void Update(int l, int r, int x, int y, int k);
int main()
{
int n, m=1000000, i, j;
LL t;
char str[30];
creat(1, m, 1);
while(~scanf("%s %d %I64d", str, &n, &t))
{
if(str[0] == 'A'){
a[t] += n;
Update(1, m, t, n, 1);
}
else{
if(n > p[1])
printf("UNHAPPY\n");
else{
LL sum = querysum(1, m, n, 1);
if(sum <= t){
printf("HAPPY\n");
while(n)
{
int id = queryid(1, m, 1);
LL x = min((LL)n, a[id]);
Update(1, m, id, -x, 1);
a[id] -= x, n -= x;
}
}
else
printf("UNHAPPY\n");
}
}
}
return 0;
}
void creat(int l, int r, int k)
{
p[k] = 0, sum[k] = 0;
if(l == r)return;
int mid=(l+r)/2;
creat(l, mid, 2*k);
creat(mid+1, r, 2*k+1);
}
void Update(int l, int r, int x, int y, int k)
{
if(l == r){
p[k] += y;
sum[k] += (LL)y*l;
return;
}
int mid = (l+r)/2;
if(x<=mid)Update(l, mid, x, y, 2*k);
else Update(mid+1, r, x, y, 2*k+1);
p[k] = p[2*k]+p[2*k+1];
sum[k] = sum[2*k]+sum[2*k+1];
}
LL querysum(int l, int r, int x, int k)
{
if(l == r)return (LL)l*x;
int mid = (l+r)/2;
if(x<=p[2*k])return querysum(l, mid, x, 2*k);
else return sum[2*k]+querysum(mid+1, r, x-p[2*k], 2*k+1);
}
LL queryid(int l, int r, int k)
{
if(l == r)return l;
int mid = (l+r)/2;
if(p[2*k])return queryid(l, mid, 2*k);
else return queryid(mid+1, r, 2*k+1);
}