V - Ice-cream Tycoon(线段树)

来源:互联网 发布:九维外呼软件 编辑:程序博客网 时间:2024/06/06 01:07

http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=216#problem/V


有两种操作,ARRIVE a b 表示单价为b的冰激凌的进货数目为a,BUY a b表示同学共拿b元钱,想买a个尽量便宜的冰激凌,若能购买到,输出"HAPPY",否则输出"UNHAPPY”

操作挺简单,单点更新然后push_up。但是写起来感觉挺麻烦。

首先先读入所有的操作,将进货的冰激凌单价离散化,建立线段树,然后按读入顺序,对于"ARRIVE"操作,更新相应的冰激凌的数目及价格,对“BUY"操作,优先搜索左子树,即尽量买便宜的,若能购买,再去更新相应区间的数目及价钱。


#include <stdio.h>#include <iostream>#include <map>#include <set>#include <list>#include <stack>#include <vector>#include <math.h>#include <string.h>#include <queue>#include <string>#include <stdlib.h>#include <algorithm>#define LL long long#define eps 1e-12#define PI acos(-1.0)#define PP pair<LL,LL>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 100010;const int mod = 1000000007;struct Info{    char str[10];    LL num;    LL mon;} info[maxn];struct node{    int l,r;    LL num; //冰激凌数目    LL sum;//总价钱    LL price;//一种冰激凌的单价} tree[maxn*4];LL x[maxn];int Binsearch(int l, int r, LL key){    int mid,low = l,high = r;    while(high >= low)    {        mid = (low + high) >> 1;        if(x[mid] == key)            return mid;        if(x[mid] > key)            high = mid - 1;        else low = mid + 1;    }    return -1;}void build(int v, int l, int r){    tree[v].l = l;    tree[v].r = r;    tree[v].num = tree[v].sum = tree[v].price = 0;    if(l == r)        return;    int mid = (l+r)>>1;    build(v*2,l,mid);    build(v*2+1,mid+1,r);}void push_down(int v){if(tree[v].l == tree[v].r)return;if(tree[v].num == 0 && tree[v].sum == 0){tree[v*2].num = tree[v*2+1].num = 0;tree[v*2].sum = tree[v*2+1].sum = 0;}}void push_up(int v){tree[v].num = tree[v*2].num + tree[v*2+1].num;tree[v].sum = tree[v*2].sum + tree[v*2+1].sum;}void update(int v, int pos, LL num, LL mon, LL t){    if(tree[v].l == tree[v].r)    {        if(tree[v].price == 0)            tree[v].price = mon;tree[v].num += num;tree[v].sum += t;        return;    }push_down(v); //重点,不要遗漏。    int mid = (tree[v].l + tree[v].r)>>1;    if(pos <= mid)        update(v*2,pos,num,mon,t);    else        update(v*2+1,pos,num,mon,t);push_up(v);}void update_1(int v, LL num, LL sum){tree[v].num -= num;tree[v].sum -= sum;if(tree[v].l == tree[v].r)return;if(tree[v*2].num >= num)update_1(v*2,num,sum);else{LL tmp1 = num - tree[v*2].num;LL tmp2 = sum - tree[v*2].sum;tree[v*2].num = 0;tree[v*2].sum = 0;update_1(v*2+1,tmp1,tmp2);}}LL query(int v, LL num){    if(tree[v].num < num)        return -1;    if(tree[v].num == num)    {        return tree[v].sum;    }    if(tree[v].l == tree[v].r)    {        return tree[v].price * num;    }    if(tree[v*2].num >= num)        return query(v*2,num);    else    {        LL res = query(v*2+1,num-tree[v*2].num);        return tree[v*2].sum + res;    }}int main(){    int t1,t2,k;    LL a,b;    char ch[10];    t1 = 0;    t2 = 0;    while(~scanf("%s %I64d %I64d",ch,&a,&b))    {        struct Info tmp;        strcpy(tmp.str,ch);        tmp.num = a;        tmp.mon = b;        info[++t1] = tmp;        if(ch[0] == 'A')            x[++t2] = b;    }    sort(x+1,x+1+t2);    k = 1;    for(int i = 2; i <= t2; i++)    {        if(x[i] != x[i-1])            x[++k] = x[i];    }    build(1,1,k);    for(int i = 1; i <= t1; i++)    {        if(info[i].str[0] == 'A')        {            int pos = Binsearch(1,k,info[i].mon);            LL t = info[i].num*info[i].mon;            update(1,pos,info[i].num,info[i].mon,t);//单点更新冰激凌的数目,价格和单价        }        else        {            LL res = query(1,info[i].num);            if(res == -1) //总数目小于购买数目                printf("UNHAPPY\n");            else            {                if(info[i].mon >= res){printf("HAPPY\n");update_1(1,info[i].num,res);//能购买,就去更新相应区间的数目及价钱}else printf("UNHAPPY\n");            }        }    }    return 0;}


0 0
原创粉丝点击