hdu 3954 Level up

http://acm.hdu.edu.cn/showproblem.php?pid=3954


终于AC了,这个题目思路是没问题,但是我就是出现各种各样的细节错误,写线段树都有很多细节要注意的,尤其是带有延迟标记的线段树,各个变量之间数值的传递思路一定要清晰才行……

 每个节点记录的变量:

   level : 表示该节点表示区间中的点的最大等级

   Max :  表示该节点表示区间中的点的最大经验值

   need: 表示该节点表示区间中的点要升级的最小需要的怪物的ei

 延迟标记: col


#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int inf=0x3fffffff;
const int maxn=10010;

typedef long long ll;
ll col[maxn<<2],Max[maxn<<2],need[maxn<<2],level[maxn<<2],ned[12];

void build(int l,int r,int rt)
{
    col[rt]=Max[rt]=0;
    level[rt]=1;
    need[rt]=ned[2];
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void pushdown(int rt)
{
    if(col[rt]){
       col[rt<<1]+=col[rt];
       col[rt<<1|1]+=col[rt];
       Max[rt<<1]+=level[rt<<1]*col[rt];
       Max[rt<<1|1]+=level[rt<<1|1]*col[rt];
       need[rt<<1|1]-=col[rt];
       need[rt<<1]-=col[rt];
       col[rt]=0;
    }
}
void pushup(int rt)
{
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
    level[rt]=max(level[rt<<1],level[rt<<1|1]);
    need[rt]=min(need[rt<<1],need[rt<<1|1]);
}
void update(int L,int R,int val,int l,int r,int rt)
{
    //cout<<l<<" "<<r<<" "<<rt<<" "<<need[rt]<<endl;
    if(L<=l&&R>=r){
         if(val>=need[rt]){
              if(l==r){
                  Max[rt]+=val*level[rt];
                  ll &now=level[rt];
                  while(Max[rt]>=ned[now+1]) now++;
                  need[rt]=(ned[now+1]-Max[rt])/now + ((ned[now+1]-Max[rt])%now!=0); //我写成了 need[rt]=(ned[now+1]-ned[now])/now + ((ned[now+1]-ned[now])%now!=0);
              }else {
                pushdown(rt);
                int m=(l+r)>>1;
                update(L,R,val,lson);
                update(L,R,val,rson);
                pushup(rt);  //当时写忘了,pushup
              }
         }else{
            col[rt]+=val;
            Max[rt]+=level[rt]*val;
            need[rt]-=val;
         }
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,val,lson);
    if(R>m)  update(L,R,val,rson);
    pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r) return Max[rt];
    pushdown(rt);
    int m=(l+r)>>1;
    ll ret1=0,ret2=0;
    if(L<=m) ret1=query(L,R,lson);
    if(R>m)  ret2=query(L,R,rson);
    pushup(rt);
    return max(ret1,ret2);
}
int main()
{
    char ord[5];
    int n,m,l,r,a,ca,cas=1,k;
    scanf("%d",&ca);
    while(ca--)
    {
        scanf("%d%d%d",&n,&k,&m);
        ned[1]=0;
        for(int i=2;i<=k;i++)  scanf("%d",&ned[i]);
        ned[k+1]=inf;
        build(1,n,1);
        printf("Case %d:\n",cas++);
        while(m--){
            scanf("%s",ord);
            if(ord[0]=='W'){
                scanf("%d%d%d",&l,&r,&a);
                update(l,r,a,1,n,1);
            }else{
                scanf("%d%d",&l,&r);
                printf("%I64d\n",query(l,r,1,n,1));
            }
        }
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值