HDU 3954 level up (line segment tree)

Topic link
Topic idea: There are n roles, k levels, and q questions. At the beginning, all characters have 0 experience and level 1. Two operations can be performed. Enter W lre to add level *e to the character experience in the [l,r] interval, and enter Q lr to query the maximum experience value in the [l,r] interval.
Idea: The first idea after seeing the question is to maintain the maximum level and experience value in the interval, and then you will encounter such a problem. When the interval is modified, it must be marked as lazy, but if you traverse the line segment tree, you must If the marked node is marked again, the information maintained at this time is incorrect. Because you may have changed the value of this interval when you marked it last time, and the experience gained will also change, so lazy marking cannot be added directly.
Since it is not possible to accumulate, what should I do? Considering that if the level is not improved after the current accumulating mark, the mark can be directly accumulated next time. However, if the level is increased, it is necessary to download a mark and modify it at the leaf node. So the information we need to maintain is one more, that is, the minimum experience index required for distance upgrade in the current interval (this refers to not the required experience value, but the same type of data as the incoming e).
You can write code after understanding this most critical point.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e4+10;
struct node
{
    
    
    int l,r;
    int mx,le;//最大经验以及它的等级
    int lazy,dis;//懒标记,距离升级的经验指数
}t[50005];
int sum[15],n,m,q;
inline void pushup(int k)
{
    
    
    t[k].dis=min(t[k<<1].dis,t[k<<1|1].dis);
    t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    t[k].le=max(t[k<<1].le,t[k<<1|1].le);
}
inline void pushdown(int k)
{
    
    
    if(t[k].lazy)
    {
    
    
        t[k<<1].mx+=t[k<<1].le*t[k].lazy;
        t[k<<1].lazy+=t[k].lazy;
        t[k<<1].dis-=t[k].lazy;

        t[k<<1|1].mx+=t[k<<1|1].le*t[k].lazy;
        t[k<<1|1].lazy+=t[k].lazy;
        t[k<<1|1].dis-=t[k].lazy;

        t[k].lazy=0;
    }
}
void build(int k,int l,int r)
{
    
    
    t[k].l=l;
    t[k].r=r;
    t[k].lazy=0;
    t[k].dis=sum[1];
    t[k].mx=0;
    t[k].le=1;
    if(l==r) return;
    else
    {
    
    
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
}
void update(int k,int l,int r,int e)
{
    
    
    if(t[k].l==t[k].r)//叶子结点
    {
    
    
        t[k].mx+=t[k].le*e;
        while(sum[t[k].le]<=t[k].mx) ++t[k].le;
        t[k].dis=(sum[t[k].le]-t[k].mx)/t[k].le+((sum[t[k].le]-t[k].mx)%t[k].le!=0);
        return;
    }
    else if(t[k].l==l&&t[k].r==r)
    {
    
    
        if(e>=t[k].dis)
        {
    
    
            pushdown(k);
            int mid=(l+r)>>1;
            update(k<<1,l,mid,e);
            update(k<<1|1,mid+1,r,e);
            pushup(k);
        }
        else
        {
    
    
            t[k].mx+=t[k].le*e;
            t[k].lazy+=e;
            t[k].dis-=e;
        }
        return;
    }
    else
    {
    
    
        pushdown(k);
        int mid=(t[k].l+t[k].r)>>1;
        if(r<=mid) update(k<<1,l,r,e);
        else if(l>mid) update(k<<1|1,l,r,e);
        else
        {
    
    
            update(k<<1,l,mid,e);
            update(k<<1|1,mid+1,r,e);
        }
        pushup(k);
    }
}
int query(int k,int l,int r)
{
    
    
    if(t[k].l==l&&t[k].r==r) return t[k].mx;
    else
    {
    
    
        pushdown(k);
        int mid=(t[k].l+t[k].r)>>1;
        if(r<=mid) return query(k<<1,l,r);
        else if(l>mid) return query(k<<1|1,l,r);
        else return max(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
    }
}
int main()
{
    
    
    int T,cas=0;
    scanf("%d",&T);
    while(T--)
    {
    
    
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<m;++i) scanf("%d",&sum[i]);
        sum[m]=(1<<30);
        int l,r,e;
        printf("Case %d:\n",++cas);
        build(1,1,n);
        while(q--)
        {
    
    
            char s[5];
            scanf("%s",s);
            if(s[0]=='W')
            {
    
    
                scanf("%d%d%d",&l,&r,&e);
                update(1,l,r,e);
            }
            else
            {
    
    
                scanf("%d%d",&l,&r);
                printf("%d\n",query(1,l,r));
            }
        }
        printf("\n");
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/amazingee/article/details/107644868