Level up 【HDU - 3954】【线段树+思维】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/88352805

题目链接


  不错的题呀,好几发才过,一开始的时候,我的想法是去查询是否整个区间都达到了等级K,然后都达到了等级K之后就是直接都不断的往上涨就是了——结局肯定是TLE,都不需要多想(但是我还是尝试了一发!)

  那么接下去怎么进行优化呢?上面的这个做法说明出了一个问题就是存在了过程中会有很高的复杂度,就是我们要去优化的是在每个等级时候的状态,不要看到就直接更新到叶子节点。于是乎就变成了怎样去更新的这么一个问题了。

  用一个need[]去记录每个区间距离升级还需要的最小等效经验,为什么要称之为“等效”呢,是因为,我将该经验需求除以其等级,得到的值,不就是所有该区间上的点的共性的值了吗?

  剩下的就是去更新这个问题了,有些时候还是要更新到叶子节点,但是这个时候的复杂度已经降了很多了。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e4 + 7;
int N, K, Q, level[15], tree[maxN<<2], lazy[maxN<<2], need[maxN<<2];
inline void pushup(int rt)
{
    tree[rt] = max(tree[lsn], tree[rsn]);
    need[rt] = min(need[lsn], need[rsn]);
}
inline void buildTree(int rt, int l, int r)
{
    need[rt] = level[2];
    lazy[rt] = 0;
    tree[rt] = 0;
    if(l == r) return;
    int mid = HalF;
    buildTree(Lson);
    buildTree(Rson);
}
inline void pushdown(int rt)
{
    if(lazy[rt])
    {
        int grade_l = (int)(upper_bound(level + 1, level + K + 2, tree[lsn]) - level - 1);
        int grade_r = (int)(upper_bound(level + 1, level + K + 2, tree[rsn]) - level - 1);
        tree[lsn] += lazy[rt] * grade_l;
        tree[rsn] += lazy[rt] * grade_r;
        need[lsn] -= lazy[rt];
        need[rsn] -= lazy[rt];
        lazy[lsn] += lazy[rt];
        lazy[rsn] += lazy[rt];
        lazy[rt] = 0;
    }
}
inline void update(int rt, int l, int r, int ql, int qr, int val)
{
    if(ql <= l && qr >= r && need[rt] > val)
    {
        int grade = (int)(upper_bound(level + 1, level + K + 2, tree[rt]) - level - 1);
        lazy[rt] += val;
        tree[rt] += val * grade;
        need[rt] -= val;
        return;
    }
    if(l == r)
    {
        int grade = (int)(upper_bound(level + 1, level + K + 2, tree[rt]) - level - 1);
        tree[rt] += grade * val;
        grade = (int)(upper_bound(level + 1, level + K + 2, tree[rt]) - level - 1);
        need[rt] = ( level[grade+1] - tree[rt] )/grade + ( ( level[grade+1] - tree[rt] )%grade != 0 );
        return;
    }
    pushdown(rt);
    int mid = HalF;
    if(ql <= mid) update(QL, val);
    if(qr > mid) update(QR, val);
    pushup(rt);
}
inline int query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && qr >= r) return tree[rt];
    pushdown(rt);
    int mid = HalF;
    if(qr <= mid) return query(QL);
    else if(ql > mid)return query(QR);
    else return max(query(QL), query(QR));
}
int main()
{
    int T;  scanf("%d", &T);
    for(int Cas=1; Cas<=T; Cas++)
    {
        scanf("%d%d%d", &N, &K, &Q);
        level[1] = 0;
        for(int i=2; i<=K; i++) scanf("%d", &level[i]);
        level[K+1] = INF;
        buildTree(1, 1, N);
        char op[3]; int x, y, z;
        printf("Case %d:\n", Cas);
        while(Q--)
        {
            scanf("%s%d%d", op, &x, &y);
            if(op[0] == 'W')
            {
                scanf("%d", &z);
                update(1, 1, N, x, y, z);
            }
            else printf("%d\n", query(1, 1, N, x, y));
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/88352805