HDU 3954 Level up

来源:互联网 发布:nginx过滤ip 编辑:程序博客网 时间:2024/05/17 09:25

题目地址
题意:就是打怪升级,告诉你升到该级的经验是多少,然后你获得的经验是你的等级乘以该怪所给的经验,求出一段区间中的最大经验值
思路:用结构体分别记录该段区间的最大经验值以及想要升级的最小经验基数(就是这个基数乘以最大等级会使得能够升级)还有该区间的最大等级,当你给的经验都不能让最小经验基数升级的话就自己更新这段区间以及延迟标记就好了,如果能升级再向下更新,直到找到完整升级的那个区间,其他的就是正常线段树了。
PS:解释下为什么要用最小经验基数的原因,因为有可能出现级数和所需经验不匹配的情况(因为他每次得到的经验是和当前等级绑定的),所以最好的方式是用所需经验和当前等级的比值排序,这才能更好的表示出当前区域最先升级的所要的经验。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 15010#define LL long long#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1using namespace std;const LL mod = 1e9 + 7;const double eps = 1e-9;int num[N];int n, q, m;struct node {    int level, mx, need, lazy;//最高的等级,经验,升级所需要的最少的经验基数,延迟标记    void init() { level = 1; mx = 0, lazy = 0; need = num[2]; }    void find(LL val) {        mx += level*val;        need -= val;        lazy += val;    }}sum[N << 2];//线段树主体struct Segment__Tree {    int x, y;    void pushUp(int ans) {        sum[ans].mx = max(sum[ans << 1].mx, sum[ans << 1 | 1].mx);        sum[ans].level = max(sum[ans << 1].level, sum[ans << 1 | 1].level);        sum[ans].need = min(sum[ans << 1].need, sum[ans << 1 | 1].need);    }    void pushDown(int ans) {        if (sum[ans].lazy) {            sum[ans << 1].lazy += sum[ans].lazy;            sum[ans << 1].mx += sum[ans].lazy*sum[ans << 1].level;            sum[ans << 1].need -= sum[ans].lazy;            sum[ans << 1 | 1].lazy += sum[ans].lazy;            sum[ans << 1 | 1].mx += sum[ans].lazy*sum[ans << 1 | 1].level;            sum[ans << 1 | 1].need -= sum[ans].lazy;        }        sum[ans].lazy = 0;    }    void build(int l, int r, int ans) {        sum[ans].init();        if (l == r) {            return;        }        int mid = (l + r) >> 1;        build(lson);        build(rson);    }    int solve(int l, int r, int ans) {        if (l >= x&&r <= y) {            return sum[ans].mx;        }        int mid = (l + r) >> 1;        pushDown(ans);        if (mid<x) {            return solve(rson);        }        else if (mid >= y) {            return solve(lson);        }        else {            return max(solve(lson), solve(rson));        }    }    void updata(int l, int r, int ans, int nums) {        if (l == r) {            sum[ans].mx += nums*sum[ans].level;            while (sum[ans].mx >= num[sum[ans].level + 1]) {                sum[ans].level++;            }            sum[ans].need = (num[sum[ans].level + 1] - sum[ans].mx) / sum[ans].level + ((num[sum[ans].level + 1] - sum[ans].mx) % sum[ans].level != 0);            return;        }        if (l >= x&&r <= y) {            if (sum[ans].need > nums) {                sum[ans].find(nums);            }            else {                int mid = (l + r) / 2;                pushDown(ans);                updata(lson, nums);                updata(rson, nums);                pushUp(ans);            }            return;        }        int mid = (l + r) >> 1;        pushDown(ans);        if (mid<x) {            updata(rson, nums);        }        else if (mid >= y) {            updata(lson, nums);        }        else {            updata(lson, nums);            updata(rson, nums);        }        pushUp(ans);    }};int main() {    cin.sync_with_stdio(false);    int c;    char s;    int T;    Segment__Tree tree;    cin >> T;    for (int Case = 1; Case <= T; Case++) {        cin >> n >> m >> q;        num[1] = 0;        for (int i = 2; i <= m; i++) {            cin >> num[i];        }        num[m + 1] = inf;        tree.build(1, n, 1);        cout << "Case " << Case << ":" << endl;        while (q--) {            cin >> s >> tree.x >> tree.y;            if (s == 'Q') {                cout << tree.solve(1, n, 1) << endl;;            }            else {                cin >> c;                tree.updata(1, n, 1, c);            }        }        cout << endl;    }    return 0;}
原创粉丝点击