HDU 3954 Level up

来源:互联网 发布:电脑不能打开淘宝网 编辑:程序博客网 时间:2024/05/21 11:55

HDU 3954 Level up
链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3954
题意:给你n个英雄,现在来了很多波怪物,每波怪物的会带来经验使英雄升级,英雄的得到的经验为其等级*e;询问某段区间的最大经验;
思路:
因为英雄的等级k不超过10,那么每个英雄升级的次数不会超过10次,so我们对,每次来的e判断会不会使这段区间的英雄升级,如果有暴力单点更新,没有记录其e,return ;关键在与确定区间的最小升级系数;
rest = (level[max_k+1] - max_exp)/max_k;因为rest的改变是从单点改变的,所以rest是区间的最小得到那个经验系数,所以rest的值只能比实际小,所以这里向下取整就可以了;没有必要向上取整;

#include<bits/stdc++.h>#define LL long longusing namespace std;const int maxn = 1e4 + 99;int level[20], k;struct segtree {    int l, r;    int max_exp, max_k;    int exp_lazy;    int rest;}tr[maxn<<2];void build(int l, int r, int pos){    tr[pos].l = l; tr[pos].r = r;    tr[pos].max_exp = 0; tr[pos].exp_lazy = 0;    tr[pos].rest = level[2];    tr[pos].max_k = 1;    if (l == r)return;    int mid = l + r >> 1;    build(l, mid, pos << 1);    build(mid + 1, r, pos << 1 | 1);}void push_up(int pos){    tr[pos].rest = min(tr[pos << 1].rest, tr[pos << 1 | 1].rest);//维护区间的最小系数    tr[pos].max_exp = max(tr[pos << 1].max_exp, tr[pos << 1 | 1].max_exp);    tr[pos].max_k = max(tr[pos << 1].max_k, tr[pos << 1 | 1].max_k);}void push_down(int pos){    if (tr[pos].exp_lazy == 0)return;    tr[pos<<1].max_exp += tr[pos<<1].max_k*tr[pos].exp_lazy;    tr[pos << 1|1].max_exp += tr[pos<<1|1].max_k*tr[pos].exp_lazy;//一定是叶子节点的k*父亲节点的lazy_exp;    tr[pos << 1].exp_lazy += tr[pos].exp_lazy;    tr[pos << 1 | 1].exp_lazy += tr[pos].exp_lazy;    tr[pos << 1].rest -= tr[pos].exp_lazy;    tr[pos << 1 | 1].rest -= tr[pos].exp_lazy;    tr[pos].exp_lazy = 0;}int find_k(int exp){    for (int i = k; i >= 2; --i)if (level[i] <= exp)return i;    return 1;}void update(int ll, int rr, int e, int pos){    if (ll == tr[pos].l&&tr[pos].r == rr)    {        if (tr[pos].rest > e)         {            tr[pos].max_exp += tr[pos].max_k*e;            tr[pos].rest -= e;            tr[pos].exp_lazy += e;            return;        }        if (ll == rr)        {                tr[pos].max_exp += e*tr[pos].max_k;            int rank = find_k(tr[pos].max_exp);            tr[pos].max_k = rank;            tr[pos].exp_lazy = 0;            tr[pos].rest = (level[tr[pos].max_k + 1] - tr[pos].max_exp) / tr[pos].max_k;            if (tr[pos].max_k == k) tr[pos].rest = 1 << 30;//这里一定要写,,,等级达到max后就不能升级,so,rest =  INF;            return;        }    }    push_down(pos);    int mid = tr[pos].l + tr[pos].r >> 1;    if (mid >= rr) update(ll, rr, e, pos << 1);    else if (mid < ll)update(ll, rr, e, pos << 1 | 1);    else    {        update(ll, mid, e, pos << 1);        update(mid + 1, rr, e, pos << 1 | 1);    }    push_up(pos);}int ask_ans(int ll, int rr, int pos){    if (ll == tr[pos].l&&tr[pos].r == rr)  return tr[pos].max_exp;    push_down(pos);    int mid = tr[pos].l + tr[pos].r >> 1;    if (mid >= rr)  return ask_ans(ll, rr, pos << 1);    else if (mid < ll) return ask_ans(ll, rr, pos << 1 | 1);    else return max(ask_ans(ll, mid, pos << 1), ask_ans(mid + 1, rr, pos << 1 | 1));}int main(){    int t, ks = 1;    scanf("%d", &t);    while (t--)    {        memset(level, 0, sizeof level);        printf("Case %d:\n", ks++);        int n, qw;        scanf("%d%d%d", &n, &k, &qw);        build(1, n, 1);        for (int i = 2; i <= k; ++i)scanf("%d", &level[i]);        while (qw--)        {            char que;            scanf(" %c ", &que);            if (que == 'Q')            {                int l, r;                scanf("%d%d", &l, &r);                printf("%d\n", ask_ans(l, r, 1));            }            else            {                int l, r, e;                scanf("%d%d%d", &l, &r, &e);                update(l, r, e, 1);            }        }        puts("");    }    return 0;}
原创粉丝点击