zoukankan      html  css  js  c++  java
  • HDU3954 Level up

    HDU3954 Level up

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


    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)
    ******************************************************************************
    题目大意:有n个人打怪升级,每一波怪具有e的经验由编号为a到b的人打掉并获得经验,每个人获得的经验为这个人当前等级k*e的经验,当一个人的经验到答规定范围他就可以升级。然后有几次询问,问从a到b这些人中经验最高的人的经验是多少。
    解体思路:线段树变种,可以说变种吗?大概是拓展应用吧,我觉得是把延时标记给拓展了一下。对于线段树每个节点,首先有固定的左端点和右端点,然后千变万化的就是延时标记。这道题的突破点在人的升级上。如果每次把经验都加到每个叶子,也就是每个人上,然后再返回,那么线段树就毫无意义了,我们希望的是,让经验加到一段区间里面,然后可以马上返回,这时候,我在每个节点定义了一个val数组,记录这颗子树下面,每个等级的人的最高经验,下次如果有经验加在这个区间里面,而这段区间里面的人加上这个经验都不会升级,那就可以暂时把经验存在这个节点而不用下传了,只有当经验加下去,人要升级了,才往下传,这个延时标记比较犀利。
    详见代码:
    //#pragma comment(linker,"/STACK:65536000")
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <stdlib.h>
    #include <iostream>
    #include <queue>
    #include <stack>
    #include <string>
    #include <map>
    #include <vector>
    #include <algorithm>
    #define N 10005
    #define M
    #define E
    #define inf 0x3f3f3f3f
    #define eps 1e-8
    #define linf (LL)1<<60
    #define dinf 1e20
    #define LL long long
    #define clr(a,b) memset(a,b,sizeof(a))
    #define D(a) ((a)*(a))
    using namespace std;
    
    struct Lt
    {
        int le,ri,val[12],flag,rst;
    }lt[N*6];
    
    int lim[12],n,k,q;
    
    void build(int rt,int le,int ri)
    {
        lt[rt].le=le;
        lt[rt].ri=ri;
        clr(lt[rt].val,-1);
        lt[rt].val[1]=0;
        lt[rt].flag=0;
        lt[rt].rst=0;
        if(le==ri)return ;
        int mid=(le+ri)>>1;
        build(rt<<1,le,mid);
        build(rt<<1|1,mid+1,ri);
    }
    
    void update(int rt,int le,int ri,int rst)
    {
        if(lt[rt].le==lt[rt].ri)
        {
            lt[rt].flag=1;
            int id;
            for(id=1;id<=k;id++)if(~lt[rt].val[id])break;
            int v=(lt[rt].rst+rst)*id+lt[rt].val[id];
            lt[rt].val[id]=-1;
            for(id=1;id<k;id++)if(v<lim[id])break;
            lt[rt].val[id]=v;
            lt[rt].rst=0;
            return ;
        }
        if(lt[rt].le==le&&lt[rt].ri==ri)
        {
            int f=0;
            for(int i=1;i<k&&!f;i++)
                if(~lt[rt].val[i]&&lt[rt].val[i]+i*(lt[rt].rst+rst)>=lim[i])
                    f=1;
            if(!f)
            {
                lt[rt].rst+=rst;
                lt[rt].flag=1;
                return ;
            }
        }
        if(lt[rt].flag)
        {
            update(rt<<1,lt[rt<<1].le,lt[rt<<1].ri,lt[rt].rst);
            update(rt<<1|1,lt[rt<<1|1].le,lt[rt<<1|1].ri,lt[rt].rst);
            lt[rt].flag=0;clr(lt[rt].val,-1);lt[rt].rst=0;
        }
        int mid=(lt[rt].le+lt[rt].ri)>>1;
        if(ri<=mid)update(rt<<1,le,ri,rst);
        else if(le>mid)update(rt<<1|1,le,ri,rst);
        else
        {
            update(rt<<1,le,mid,rst);
            update(rt<<1|1,mid+1,ri,rst);
        }
        for(int i=1;i<=k;i++)
        {
            if(~lt[rt<<1].val[i]&&~lt[rt<<1|1].val[i])
                lt[rt].val[i]=max(lt[rt<<1].val[i]+i*lt[rt<<1].rst,lt[rt<<1|1].val[i]+i*lt[rt<<1|1].rst);
            else if(~lt[rt<<1].val[i])lt[rt].val[i]=lt[rt<<1].val[i]+i*lt[rt<<1].rst;
            else if(~lt[rt<<1|1].val[i])lt[rt].val[i]=lt[rt<<1|1].val[i]+i*lt[rt<<1|1].rst;
            else lt[rt].val[i]=-1;
        }
    }
    
    int query(int rt,int le,int ri,int rst)
    {
        if(lt[rt].le==le&&lt[rt].ri==ri)
        {
            for(int i=k;i>=1;i--)
                if(~lt[rt].val[i])
                    return lt[rt].val[i]+lt[rt].rst*i+rst*i;
        }
        if(lt[rt].flag)rst+=lt[rt].rst;
        int mid=(lt[rt].le+lt[rt].ri)>>1;
        if(ri<=mid)return query(rt<<1,le,ri,rst);
        else if(le>mid)return query(rt<<1|1,le,ri,rst);
        else return max(query(rt<<1,le,mid,rst),query(rt<<1|1,mid+1,ri,rst));
    }
    
    int main()
    {
        //freopen("/home/fatedayt/in","r",stdin);
        //freopen("/home/fatedayt/out1","w",stdout);
    	int ncase;
    	scanf("%d",&ncase);
    	for(int h=1;h<=ncase;h++)
    	{
    	    scanf("%d%d%d",&n,&k,&q);
    	    for(int i=1;i<k;i++)scanf("%d",&lim[i]);
    	    build(1,1,n);
    	    printf("Case %d:\n",h);
    	    for(int i=1;i<=q;i++)
    	    {
    	        char d[3];
    	        scanf("%s",d);
    	        if(d[0]=='W')
    	        {
    	            int a,b,c;
    	            scanf("%d%d%d",&a,&b,&c);
    	            update(1,a,b,c);
    	            a++;
    	        }
    	        else
    	        {
    	            int a,b;
    	            scanf("%d%d",&a,&b);
    	            printf("%d\n",query(1,a,b,0));
    	        }
    	    }
    	    puts("");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Windows Phone 7之初体验(三.开发问答(转发))
    Windows phone 7 之初体验(一.安装Windows phone 7 sdk)
    python 程序的性能分析优化(huffman编码程序性能分析的一个小结论)
    图的深度优先遍历,及常见的扩展算法
    递归回溯与迭代回溯算法框架,打印在n个数字中取k个数字的所有可能
    python 实现的范式huffman压缩,解压缩
    <读书笔记> Thinking in python (Python 设计模式) 3. Proxy and State模式
    二分查找极其变形算法
    <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现
    <转载>openmesh文档的非专业翻译by kidux(学习generative programming非常好的库)
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2450048.html
Copyright © 2011-2022 走看看