HDU 3954レベルアップ(ラインセグメントツリー)

トピックリンク
トピックのアイデア:n個の役割、k個のレベル、およびq個の質問があります。最初は、すべてのキャラクターの経験が0で、レベル1です。2つの操作を実行できます。Wlreを入力して[l、r]間隔のキャラクターエクスペリエンスにレベル* eを追加し、Qlrを入力して[l、r]間隔の最大エクスペリエンス値を照会します。
アイデア:質問を見た後の最初のアイデアは、間隔で最大レベルと経験値を維持することです。そうすると、そのような問題が発生します。間隔を変更すると、レイジーとしてマークする必要がありますが、ラインセグメントツリーをトラバースする場合は、マークされたノードが再度マークされた場合、この時点で維持されている情報は正しくありません。前回マークしたときにこの間隔の値を変更した可能性があり、得られる経験も変わるため、レイジーマーキングを直接追加することはできません。
累積できないので、現在の累積マーク以降にレベルが上がらなければ、次回もマークを累積できるのでどうしたらいいですか。ただし、レベルを上げる場合は、マークをダウンロードしてリーフノードで変更する必要があります。したがって、維持する必要のある情報はもう1つです。つまり、現在の間隔で距離をアップグレードするために必要な最小エクスペリエンスインデックスです(これは、必要なエクスペリエンス値ではなく、着信eと同じタイプのデータを指します)。
この最も重要なポイントを理解した後、コードを書くことができます。

#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;
}

おすすめ

転載: blog.csdn.net/amazingee/article/details/107644868