线段树特殊懒惰标记hdu3954(hdu4902)

F.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts
Problem Archive
Realtime Judge Status
Authors Ranklist
 
      C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
Author  lee
Mail Mail 0(0)
Control Panel  Control Panel  
Sign Out  Sign Out

即将截止!!!【BestCoder Round #3】8月3号19:00~21:00(赛前30分钟停止注册比赛)
不熟悉BestCoder的比赛?看看这里—>《BestCoder用户手册》下载链接

Level up

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


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.
线段树特殊懒惰标记hdu3954(hdu4902)_第1张图片

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


题意:有N个英雄,每个英雄的初始等级为1,初始经验为0,有K个等级,QW个操作。接下来一行中有K-1个数值,代表升到等级2,等级3……所要达到的经验。接下来的QW行里,每行是一个操作,操作有两类,(1)"l r e",代表区间[l,r]里的每个英雄将得到e乘以他的等级的经验。(2)"l r",表示查询区间[l,r]里经验最大值。

思路:线段树维护一个maxv(表示当前段最大值),level(表示当前段最大的level,用来更新maxv用的),cnt(延迟标记,记录当前段的经验值e),needv(表示到达下一阶段还需要的e)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=10010;
const int INF=1000000000;
typedef long long LL;

int need[15];
int n,k,q;

struct IntervalTree
{
    LL maxv[maxn<<3];
    LL needv[maxn<<3];
    LL level[maxn<<3];
    LL cnt[maxn<<3];
    void build(int o,int l,int r)
    {
        level[o]=1;
        maxv[o]=cnt[o]=0;
        needv[o]=need[2];
        if(l==r)return ;
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
    }
    void maintain1(int o,int l,int r,int val)
    {
        maxv[o]+=val*level[o];
        LL & now=level[o];
        while(need[now+1]<=maxv[o])now++;
        needv[o]=(need[now+1]-maxv[o])/now+((need[now+1]-maxv[o])%now!=0);
    }

    void maintain2(int o,int val)
    {
        maxv[o]+=level[o]*val;
        needv[o]-=val;
        cnt[o]+=val;
    }
    void pushdown(int o,int l,int r)
    {
        if(cnt[o])
        {
            maintain2(o<<1,cnt[o]);
            maintain2(o<<1|1,cnt[o]);
            cnt[o]=0;
        }
    }
    void pushup(int o,int l,int r)
    {
        if(l>=r)return;
        level[o]=max(level[o<<1],level[o<<1|1]);
        needv[o]=min(needv[o<<1],needv[o<<1|1]);
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }

    void update(int o,int l,int r,int q1,int q2,int val)
    {
        if(q1<=l&&r<=q2)
        {
            if(val>=needv[o])
            {
                if(l==r)
                    maintain1(o,l,r,val);
                else
                {
                    pushdown(o,l,r);
                    int mid=(l+r)>>1;
                    if(q1<=mid)update(o<<1,l,mid,q1,q2,val);
                    if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,val);
                    pushup(o,l,r);
                }
            }
            else maintain2(o,val);
            return;
        }
        pushdown(o,l,r);
        int mid=(l+r)>>1;
        if(q1<=mid)update(o<<1,l,mid,q1,q2,val);
        if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,val);
        pushup(o,l,r);
    }

    LL query(int o,int l,int r,int q1,int q2)
    {
        if(q1<=l&&r<=q2)return maxv[o];
        int mid=(l+r)>>1;
        pushdown(o,l,r);
        LL x=0,y=0;
        if(q1<=mid)x=query(o<<1,l,mid,q1,q2);
        if(q2>mid)y=query(o<<1|1,mid+1,r,q1,q2);
        pushup(o,l,r);
        return max(x,y);
    }

}tree;

int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&k,&q);
        for(int i=2;i<=k;i++)scanf("%d",&need[i]);
        need[k+1]=INF;
        char op[5];
        tree.build(1,1,n);
        printf("Case %d:\n",cas++);
        while(q--)
        {
            int l,r,e;
            scanf("%s%d%d",op,&l,&r);
            if(op[0]=='W')
            {
                scanf("%d",&e);
                tree.update(1,1,n,l,r,e);
            }
            else
                cout<


在今年的多校联合也遇到了一个这样的题hdu4902和hdu4893,4893前面写过了,这里只写hdu4902

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=100010;
typedef long long LL;
int n,Q;
LL a[maxn];

LL gcd(LL x,LL y)
{
    if(y==0)return x;
    return gcd(y,x%y);
}

struct IntervalTree
{
    int setv[maxn<<3];
    LL minv[maxn<<3];
    LL maxv[maxn<<3];
    void build(int o,int l,int r)
    {
        setv[o]=-1;
        if(l==r)
        {
            minv[o]=maxv[o]=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        minv[o]=min(minv[o<<1],minv[o<<1|1]);
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }
    void pushup(int o)
    {
        minv[o]=min(minv[o<<1],minv[o<<1|1]);
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }
    void pushdown(int o,int l,int r)
    {
        if(setv[o]==1)
        {
            setv[o<<1]=setv[o<<1|1]=1;
            minv[o<<1]=minv[o<<1|1]=minv[o];
            maxv[o<<1]=maxv[o<<1|1]=maxv[o];
            setv[o]=-1;
        }

    }
    void update(int o,int l,int r,int q1,int q2,LL val,int t)
    {
        if(q1<=l&&r<=q2)
        {
            if(t==1)
            {
                setv[o]=1;
                minv[o]=maxv[o]=val;
                return;
            }
            else
            {
                if(setv[o]==1)
                {
                    if(maxv[o]>val)
                    {
                        LL tmp=gcd(maxv[o],val);
                        minv[o]=maxv[o]=tmp;
                    }
                    return;
                }
                else if(val>=maxv[o])return;
            }
        }
        if(l==r)
        {
            if(t==2&&val>1;
        if(q1<=mid)update(o<<1,l,mid,q1,q2,val,t);
        if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,val,t);
        pushup(o);
    }
    LL query(int o,int l,int r,int pos)
    {
        if(setv[o]==1)return minv[o];
        if(l==r)return minv[o];
        int mid=(l+r)>>1;
        if(pos<=mid)return query(o<<1,l,mid,pos);
        else return query(o<<1|1,mid+1,r,pos);
    }

}tree;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
        tree.build(1,1,n);
        scanf("%d",&Q);
        while(Q--)
        {
            int t,l,r;
            LL x;
            scanf("%d%d%d%I64d",&t,&l,&r,&x);
            tree.update(1,1,n,l,r,x,t);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%I64d ",tree.query(1,1,n,i));
        }
        printf("\n");
    }
    return 0;
}



你可能感兴趣的:(树状数组/线段树)