hdu3954 线段树延迟更新

延迟最小升级经验值/每级经验最大值,只能说思想屌爆啦!

历时一整天总算搞定了,大错误没有,小错误一大堆,心都碎了,只能说线段树太让人蛋疼了。两百行的代码,检查起来相当蛋疼,尤其是测试数据,各种小错误都可以过,坑爹啊。

两种AC代码如下:


延迟最小升级经验值:

#include<stdio.h>
#include<string.h>

const int size=11111;
const int INF=((1<<30)-1);

int k,need[12],lazy[size<<2],li[size<<2],ri[size<<2];
int exp[size<<2],lev[size<<2],md[size<<2];

int Max(int a1,int a2) { return a1>a2?a1:a2; }

int Min(int a1,int a2) { return a1<a2?a1:a2; }

int upgrade(int i,int tmp)
{
    while (i<k)
    {
        if (tmp<need[i]) break;
        else i++;
    }
    return i;
}

void PushUp(int rt)
{
    md[rt]=Min(md[rt<<1],md[rt<<1|1]);
    exp[rt]=Max(exp[rt<<1],exp[rt<<1|1]);
    lev[rt]=Max(lev[rt<<1],lev[rt<<1|1]);
}

void build(int rt,int l,int r)
{
    li[rt]=l;ri[rt]=r;
    lazy[rt]=exp[rt]=0;
    lev[rt]=1;
    md[rt]=need[1];
    if (l==r) return ;
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}

void PushDown(int rt)
{
    if (lazy[rt]>0)
    {
        if (li[rt]==ri[rt])
        {
            lev[rt]=upgrade(lev[rt],exp[rt]);
            md[rt]=need[lev[rt]]-exp[rt];
            return ;
        }
        int t1=rt<<1,t2=rt<<1|1;
        int v=lazy[rt];
        lazy[rt]=0;
        lazy[t1]+=v; lazy[t2]+=v;
        exp[t1]+=lev[t1]*v; exp[t2]+=lev[t2]*v;
        if (lev[t1]*v>=md[t1]) PushDown(t1);
        else  md[t1]-=lev[t1]*v;
        if (lev[t2]*v>=md[t2]) PushDown(t2);
        else  md[t2]-=lev[t2]*v;
        PushUp(rt);
    }
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if (L<=l&&r<=R)
    {
        bool flag=false;
        lazy[rt]+=v;
        exp[rt]+=lev[rt]*v;
        if (lev[rt]*v>=md[rt]) PushDown(rt);
        else  md[rt]-=lev[rt]*v;
        return ;
    }
    PushDown(rt);
    int m=(l+r)>>1;
    if (L<=m) update(rt<<1,l,m,L,R,v);
    if (R>m)  update(rt<<1|1,m+1,r,L,R,v);
    PushUp(rt);
}

int query(int rt,int l,int r,int L,int R)
{
    if (L<=l&&r<=R) return exp[rt];
    PushDown(rt);
    int m=(l+r)>>1,ans=0;
    if (L<=m) ans=Max(ans,query(rt<<1,l,m,L,R));
    if (R>m)  ans=Max(ans,query(rt<<1|1,m+1,r,L,R));
    return ans;
}

int main()
{
    int n,q,a,b,v,T,ncase=0;
    scanf("%d",&T);
    char str[5];
    while(T--)
    {
        scanf("%d %d %d",&n,&k,&q);
        for(int i=1; i<k; i++)scanf("%d",&need[i]);
        need[k]=INF;
        build(1,1,n);
        printf("Case %d:\n",++ncase);
        for(int i=0; i<q; i++)
        {
            scanf("%s",&str);
            if(str[0]=='W')
            {
                scanf("%d%d%d",&a,&b,&v);
                update(1,1,n,a,b,v);
            }
            else
            {
                scanf("%d%d",&a,&b);
                printf("%d\n",query(1,1,n,a,b));
            }
        }
        printf("\n");
    }
    return 0;
}



每级经验最大值:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

const int N = 11111;
const int INF=((1<<30)-1);

struct node
{
    int l,r;
    int lazy;
    int val[12];
} tre[N<<2];

int le[12],k;

int upgrade(int lev,int ep)
{
    while (lev<k)
        if (ep<le[lev]) break;
        else lev++;
    return lev;
}

int Max(int a,int b)
{
    return a>b?a:b;
}

void PushUp(int rt)
{
    for(int i=1; i<=k; i++)
        tre[rt].val[i]=Max(tre[rt<<1].val[i],tre[rt<<1|1].val[i]);
}

void build(int rt,int l,int r)
{
    tre[rt].l=l;
    tre[rt].r=r;
    memset(tre[rt].val,-1,sizeof(tre[rt].val));
    tre[rt].lazy=tre[rt].val[1]=0;
    if(l==r) return ;
    int m=(r+l)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}

void PushDown(int rt)
{
    if (tre[rt].l>=tre[rt].r) return ;
    if(tre[rt].lazy>0)
    {
        int t1=rt<<1;
        int t2=t1|1;
        int flag1=0,flag2=0;
        int v=tre[rt].lazy;
        tre[t1].lazy+=v;
        tre[t2].lazy+=v;
        tre[rt].lazy=0;
        for(int i=k; i>0; i--)
        {
            if(tre[t1].val[i]>=0)
            {
                tre[t1].val[i]+=i*v;
                if(tre[t1].val[i]>=le[i])
                {
                    int tmp=upgrade(i,tre[t1].val[i]);
                    tre[t1].val[tmp]=Max(tre[t1].val[tmp],tre[t1].val[i]);
                    tre[t1].val[i]=-1;
                    flag1=1;
                }
            }
            if(tre[t2].val[i]>=0)
            {
                tre[t2].val[i]+=i*v;
                if(tre[t2].val[i]>=le[i])
                {
                    int tmp=upgrade(i,tre[t2].val[i]);
                    tre[t2].val[tmp]=Max(tre[t2].val[tmp],tre[t2].val[i]);
                    tre[t2].val[i]=-1;
                    flag2=1;
                }
            }
        }
        if(flag1) PushDown(t1);
        if(flag2) PushDown(t2);
        PushUp(rt);
    }
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if(L<=l&&r<=R)
    {
        int flag=0;
        for (int i=k; i>0; i--)
        {
            if (tre[rt].val[i]>=0)
            {
                tre[rt].val[i]+=i*v;
                if (tre[rt].val[i]>=le[i]&&i!=k)
                {
                    int tmp=upgrade(i,tre[rt].val[i]);
                    tre[rt].val[tmp]=Max(tre[rt].val[tmp],tre[rt].val[i]);
                    tre[rt].val[i]=-1;
                    flag=1;
                }
            }
        }
        tre[rt].lazy+=v;
        if (flag) PushDown(rt);
        return ;
    }
    PushDown(rt);
    int m=(r+l)>>1;
    if(L<=m)update(rt<<1,l,m,L,R,v);
    if(R>m) update(rt<<1|1,m+1,r,L,R,v);
    PushUp(rt);
}

int query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)
        for (int i=k; i>0; i--)
            if (tre[rt].val[i]>=0) return tre[rt].val[i];
    PushDown(rt);
    int m=(r+l)>>1;
    int ans=0;
    if(L<=m)ans=Max(ans,query(rt<<1,l,m,L,R));
    if(R>m) ans=Max(ans,query(rt<<1|1,m+1,r,L,R));
    return ans;
}

int main()
{
    int t,n,m,a,b,v,T=0;
    scanf("%d",&t);
    char temp[5];
    while(t--)
    {
        scanf("%d%d%d",&n,&k,&m);
        build(1,1,n); le[k]=INF;
        for(int i=1; i<k; i++)scanf("%d",&le[i]);
        printf("Case %d:\n",++T);
        while (m--)
        {
            scanf("%s",&temp);
            if(temp[0]=='W')
            {
                scanf("%d%d%d",&a,&b,&v);
                update(1,1,n,a,b,v);
            }
            else
            {
                scanf("%d%d",&a,&b);
                printf("%d\n",query(1,1,n,a,b));
            }
        }
        puts("");
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值