トピックリンク
トピックのアイデア: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;
}