zoukankan      html  css  js  c++  java
  • HDU 3954 Level up

    HDU_3954

        一开始始终在纠结要怎样维护max,因为不同等级的人每次加的经验是不一样的,这样如果只用一个max来维护最大值的话是很难办的。看了胡浩的出题报告之后恍然大悟,既然一个max来维护是很难办的,那不妨就将max变成K个,max[i]表示等级为i的人的经验的最大值,这样max[i]的增加就很好处理了。

        至于如何处理一个人的升级问题,既然有了max[i],那么我们就知道每个等级上是否有人的经验达到了need[i+1],一旦有人达到就直接找到这个人,并将路径上的max[i]和max[i+1]的值更新一下即可。由于K比较小,每个人最多升级K次,而每次找一个人的复杂度是logN,所以升级操作总的复杂度是K*N*logN,是可以接受的。查询操作就比较好写了。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 10010
    #define MAXK 11
    #define INF 0x3f3f3f3f
    int N, K, QW, max[4 * MAXD][MAXK], add[4 * MAXD], need[MAXK];
    void build(int cur, int x, int y)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
        memset(max[cur], -1, sizeof(max[cur]));
        max[cur][1] = add[cur] = 0;
        if(x == y)
            return ;
        build(ls, x, mid);
        build(rs, mid + 1, y);
    }
    void init()
    {
        int i;
        scanf("%d%d%d", &N, &K, &QW);
        for(i = 1; i < K; i ++)
            scanf("%d", &need[i]);
        need[K] = INF;
        build(1, 1, N);
    }
    int getmax(int x, int y)
    {
        return x > y ? x : y;
    }
    void update(int cur)
    {
        int i, ls = cur << 1, rs = (cur << 1) | 1;
        for(i = 1; i <= K; i ++)
            max[cur][i] = getmax(max[ls][i], max[rs][i]);
    }
    void pushdown(int cur)
    {
        int ls = cur << 1, rs = (cur << 1) | 1;
        if(add[cur])
        {
            int i;
            add[ls] += add[cur], add[rs] += add[cur];
            for(i = 1; i <= K; i ++)
            {
                if(max[ls][i] != -1)
                    max[ls][i] += i * add[cur];
                if(max[rs][i] != -1)
                    max[rs][i] += i * add[cur];
            }
            add[cur] = 0;
        }
    }
    void change(int cur, int x, int y, int k)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
        if(x == y)
        {
            max[cur][k + 1] = max[cur][k];
            max[cur][k] = -1;
            return ;
        }
        pushdown(cur);
        if(max[ls][k] >= need[k])
            change(ls, x, mid, k);
        else
            change(rs, mid + 1, y, k);
        max[cur][k] = getmax(max[ls][k], max[rs][k]);
        max[cur][k + 1] = getmax(max[ls][k + 1], max[rs][k + 1]);
    }
    void refresh(int cur, int x, int y, int s, int t, int delta)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
        if(x >= s && y <= t)
        {
            int i;
            add[cur] += delta;
            for(i = 1; i <= K; i ++)
                if(max[cur][i] != -1)
                    max[cur][i] += i * delta;
            for(i = 1; i < K; i ++)
                while(max[cur][i] >= need[i])
                    change(cur, x, y, i);
            return ;
        }
        pushdown(cur);
        if(mid >= s)
            refresh(ls, x, mid, s, t, delta);
        if(mid + 1 <= t)
            refresh(rs, mid + 1, y, s, t, delta);
        update(cur);
    }
    void query(int cur, int x, int y, int s, int t, int &ans)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
        if(x >= s && y <= t)
        {
            int i;
            for(i = 1; i <= K; i ++)
                if(max[cur][i] > ans)
                    ans = max[cur][i];
            return ;
        }
        pushdown(cur);
        if(mid >= s)
            query(ls, x, mid, s, t, ans);
        if(mid + 1 <= t)
            query(rs, mid + 1, y, s, t, ans);
    }
    void solve()
    {
        int i, j, k, x, y, z, ans;
        char b[5];
        for(i = 0; i < QW; i ++)
        {
            scanf("%s", b);
            if(b[0] == 'W')
            {
                scanf("%d%d%d", &x, &y, &z);
                refresh(1, 1, N, x, y, z);
            }
            else
            {
                scanf("%d%d", &x, &y);
                ans = 0;
                query(1, 1, N, x, y, ans);
                printf("%d\n", ans);
            }
        }
    }
    int main()
    {
        int t, tt;
        scanf("%d", &t);
        for(tt = 0; tt < t; tt ++)
        {
            init();
            printf("Case %d:\n", tt + 1);
            solve();
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    pdf在线转换器
    抖音修复老照片动起来笑起来的程序app的下载地址
    FFmpeg.AutoGen Unable to load DLL 'avutil.56' 解决方法
    Array.prototype.fill 填充值被复用的问题
    Recoil Input 光标位置被重置到末尾的问题
    TypeScript 扩展全局 Window 时报错的解决
    Recoil 中默认值的正确处理
    Recoil 中多级数据联动及数据重置的合理做法
    Recoil 默认值及数据级联的使用
    Recoil 的使用
  • 原文地址:https://www.cnblogs.com/staginner/p/2444294.html
Copyright © 2011-2022 走看看