hdu 3954 Level up(线段树)

Level up

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2976    Accepted Submission(s): 823


Problem 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.
The first line of each case contains three integers N(1<=N<=10000), K(2<=K<=10) and QW(1<=QW<=10000)each represent hero number, the MAX level and querys/waves number.
Then a line with K -1 integers, Need2, Need3...Needk.(1 <= Need2 < Need3 < ... < Needk <= 10000).
Then QW lines follow, each line start with 'W' contains three integers li ri ei (1<=li<=ri<=N , 1<=ei<=10000); each line start with 'Q' contains two integers li ri (1<=li<=ri<=N).
 

Output
For each case, output the number of case in first line.(as shown in the sample output)
For each query, output the maximum Exp from li to ri.
Output a black line after each case.
 

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
Hint
Case 1: At first ,the information of each hero is 0(1),0(1),0(1) [Exp(level)] After first wave, 1(2),0(1),0(1); After second wave, 3(3),1(2),0(1); After third wave, 6(3),3(3),1(2); Case 2: The information of each hero finally: 18(5) 18(5) 25(5) 5(2) 9(2)
 

Author
NotOnlySuccess
 

Source
 

Recommend
lcy

鉴于本人数组结构有点弱...所以决定由今天开始每日一课树

题意:看到这个题目我就想到...单挑BOSS 怒刷装备 皇城PK 胜者为王 屠龙宝刀 点击就送 极品装备 一秒刷爆 幸运抽奖 惊喜不断 经典装备 极品属性 无限刷怪 双倍经验我不断的寻找 有你的世界在哪里。。。我当然不是在卖广告- -这个经常在网页弹出来的,我情不自禁就复制上来了....离题了- -

题意其实是让你杀怪升级- -&*(&(……%%……%¥……*……%%还是自己看把- -一说就想起游戏,想起就说不清楚了

题解:线段树标记经验值,级数和还有多少的值需要升级(这个是相对而言的,要除以级数),当然还有lazy标记啦~~~


#include<stdio.h>
#include<string.h>
struct tree
{
    int exp,lazy,need,level;
} t[40088];
int sum[18],n,k,m;
char s[8];
int MAX(int a,int b){ return a>b?a:b; }
int MIN(int a,int b){ return a<b?a:b; }
void build(int l,int r,int pos)
{
    int mid=(l+r)>>1;

    t[pos].need=sum[1];
    t[pos].level=1;
    t[pos].lazy=t[pos].exp=0;
    if(l==r) return;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
}
void down(int pos)
{
    t[pos<<1].exp+=t[pos].lazy*t[pos<<1].level;
    t[pos<<1].need-=t[pos].lazy;
    t[pos<<1].lazy+=t[pos].lazy;
    t[pos<<1|1].exp+=t[pos].lazy*t[pos<<1|1].level;
    t[pos<<1|1].need-=t[pos].lazy;
    t[pos<<1|1].lazy+=t[pos].lazy;
    t[pos].lazy=0;
}
void up(int pos)
{
    t[pos].exp=MAX(t[pos<<1].exp,t[pos<<1|1].exp);
    t[pos].need=MIN(t[pos<<1].need,t[pos<<1|1].need);
    t[pos].level=MAX(t[pos<<1].level,t[pos<<1|1].level);
}
void update(int l,int r,int pos,int templ,int tempr,int val)
{
    int mid=(l+r)>>1;

    if(l==r)
    {
        t[pos].exp+=t[pos].level*val;
        while(t[pos].exp>=sum[t[pos].level]) t[pos].level++;
        t[pos].need=(sum[t[pos].level]-t[pos].exp+t[pos].level-1)/t[pos].level;
        return;
    }
    if(templ<=l&&r<=tempr)
    {
        if(val>=t[pos].need)
        {
            if(t[pos].lazy) down(pos);
            update(l,mid,pos<<1,templ,mid,val);
            update(mid+1,r,pos<<1|1,mid+1,tempr,val);
            up(pos);
        }
        else
        {
            t[pos].exp+=t[pos].level*val;
            t[pos].need-=val;
            t[pos].lazy+=val;
        }
        return;
    }
    if(t[pos].lazy) down(pos);
    if(tempr<=mid) update(l,mid,pos<<1,templ,tempr,val);
    else if(templ>mid) update(mid+1,r,pos<<1|1,templ,tempr,val);
    else
    {
        update(l,mid,pos<<1,templ,mid,val);
        update(mid+1,r,pos<<1|1,mid+1,tempr,val);
    }
    up(pos);
}
int ques(int l,int r,int pos,int templ,int tempr)
{
    int mid=(l+r)>>1,res;


    if(templ<=l&&r<=tempr) return t[pos].exp;
    if(t[pos].lazy) down(pos);
    if(tempr<=mid) res=ques(l,mid,pos<<1,templ,tempr);
    else if(templ>mid) res=ques(mid+1,r,pos<<1|1,templ,tempr);
    else res=MAX(ques(l,mid,pos<<1,templ,mid),ques(mid+1,r,pos<<1|1,mid+1,tempr));
    up(pos);
    return res;
}
int main()
{
    int t,i,x,y,z,cas=1;

    scanf("%d",&t);
    while(t--)
    {
        printf("Case %d:\n",cas++);
        scanf("%d%d%d",&n,&k,&m);
        for(i=1; i<k; i++) scanf("%d",sum+i);
        sum[i]=1<<30;
        build(1,n,1);
        for(i=0; i<m; i++)
        {
            scanf("%s",s);
            if(s[0]=='W')
            {
                scanf("%d%d%d",&x,&y,&z);
                update(1,n,1,x,y,z);
            }
            else
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",ques(1,n,1,x,y));
            }
        }
        printf("\n");
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值