Level upProblem Description Level up is the task of all online games. It's very boooooooooring. There is only level up in those games, except level up.In a online game, there are N heroes numbered id from 1 to N, each begins with level 1 and 0 Experience. They need to kill monsters to get Exp and level up. There are many waves of monsters, each wave, the heroes with id from li to ri will come to kill monsters and those hero with level k will get ei*k Exp. If one hero's Exp reach Needk then the hero level up to level k immediately. After some waves, I will query the maximum Exp from li to ri. Now giving the information of each wave and Needk, please tell me the answer of my query. Input The first line is a number T(1<=T<=30), represents the number of case. The next T blocks follow each indicates a case. Output For each case, output the number of case in first line.(as shown in the sample output) Sample Input 2 3 3 5 1 2 W 1 1 1 W 1 2 1 Q 1 3 W 1 3 1 Q 1 3 5 5 8 2 10 15 16 W 5 5 9 W 3 4 5 W 1 1 2 W 2 3 2 Q 3 5 W 1 3 8 Q 1 2 Q 3 5 Sample Output Case 1: 3 6
Case 2: 9 18 25 |
题意:
有N个英雄,每个英雄的初始等级为1,初始经验为0,有K个等级,QW个操作。接下来一行中有K-1个数值,代表升到等级2,等级3……所要达到的经验。接下来的QW行里,每行是一个操作,操作有两类,(1)"l r e",代表区间[l,r]里的每个英雄将得到e乘以他的等级的经验。(2)"l r",表示查询区间[l,r]里经验最大值。有一个特殊点,就是我不是一级一级升级的,而是可以直接升,例如一共5级,升到每级的经验是 1 2 3 4,那么当英雄获得 2 经验的时候就可以直接升到3级了,不是获得1经验升到2级,再获得2经验升到3级。
题解:
线段树还是太菜了啊,感觉理解不够深刻,还应该再去学一波,这个题目就是用线段树维护区间经验最大值,区间内升级需要的最少的经验值,当我当前增加的经验小于我当前升级需要的最少经验时,我就用lazy记录下来,因为反正也不会让他升级,那么我就先记录,等之后在pushdown操作时对子区间进行更新,然后再对于某此区间,它需要升级的最小经验小于当前给的经验时,那么这段区间内就存在能够升级的点,那么我递归下去到节点中进行升级操作(我之前一直怕会T),然后就递归到那个点然后对那个点进行更改,注意有可能当前的经验值可以让级数升好多级的情况,然后更改该点的最大经验值,该点的升级所需要的最少经验值,然后在之后的pushup操作时更新父节点
代码:
#include<bits/stdc++.h>
#define N 10005
#define INF 0x3f3f3f3f
#define lson node<<1
#define rson node<<1|1
using namespace std;
int t,n,k,q,tmp=0;
int w[30];
struct ljh
{
int l,r,lazy,mx,nv,level;
//左右区间端点,lazy标记,区间最大经验值,区间内点升级需要的最少经验,级数
}e[N<<2];
inline void pushup(int node)
{
e[node].mx=max(e[lson].mx,e[rson].mx);
e[node].nv=min(e[lson].nv,e[rson].nv);
e[node].level=max(e[lson].level,e[rson].level);
}
inline void pushdown(int node)
{
if(e[node].lazy)
{
e[lson].mx+=(e[lson].level*e[node].lazy);
e[rson].mx+=(e[rson].level*e[node].lazy);
e[lson].nv-=e[node].lazy;
e[rson].nv-=e[node].lazy;
e[lson].lazy+=e[node].lazy;
e[rson].lazy+=e[node].lazy;
e[node].lazy=0;
}
}
void Build(int node,int l,int r)
{
e[node].l=l;
e[node].r=r;
e[node].lazy=0;
if(l==r)
{
e[node].mx=0;
e[node].level=1;
e[node].nv=ceil((w[e[node].level+1]-e[node].mx)/e[node].level);
return;
}
int m=(l+r)>>1;
Build(lson,l,m);
Build(rson,m+1,r);
pushup(node);
}
void Update(int node,int x,int y,int z)
{
if(x<=e[node].l&&e[node].r<=y&&e[node].nv>z)//不能升级,正常更新,进行标记,等到能升级的时候再用
{
e[node].nv-=z;
e[node].mx+=(e[node].level*z);
e[node].lazy+=z;
return;
}
if(x<=e[node].l&&e[node].r<=y&&e[node].l==e[node].r)//更新到子节点
{
e[node].mx+=(e[node].level*z);
while(e[node].mx>=w[e[node].level+1])e[node].level++; //判断能升到几级,注意一下升多级的情况
e[node].lazy=0;
e[node].nv=ceil((w[e[node].level+1]-e[node].mx)/e[node].level);//更新升级最小值
return;
}
pushdown(node);
int m=(e[node].l+e[node].r)>>1;
if(x<=m)Update(lson,x,y,z);
if(y>m)Update(rson,x,y,z);
pushup(node);
}
int Query(int node,int x,int y)
{
int Max=0;
if(x<=e[node].l&&e[node].r<=y)
{
return e[node].mx;
}
pushdown(node);
int m=(e[node].l+e[node].r)>>1;
if(x<=m)Max=max(Max,Query(lson,x,y));
if(y>m)Max=max(Max,Query(rson,x,y));
pushup(node);
return Max;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&k,&q);
memset(w,0,sizeof(w));
for(int i=2;i<=k;i++)scanf("%d",&w[i]);
w[1]=0;
w[k+1]=INF;//升到第k级后就不能再升了
Build(1,1,n);
printf("Case %d:\n",++tmp);
while(q--)
{
char op;
int x,y,z;
cin>>op;
if(op=='W')
{
scanf("%d%d%d",&x,&y,&z);
Update(1,x,y,z);
}
else
{
scanf("%d%d",&x,&y);
printf("%d\n",Query(1,x,y));
}
}
printf("\n");
}
}