hdu 3954(线段树的特殊lazy操作-更新时才遍历!)

  和经典的线段树区间lazy操作相比,区间传递的是经验系数,每个点对系数的反应是不一样的,所以向下传递的时机有所改变,不但在区间被剖分时要向下释放,在该区间有某个点要升级的时候也要释放,因为此时用区间的lazy值叠加的话会影响结果,所以此时要释放lazy,lazy只有在这个区间的点都没到达升级门槛时才可以叠加。 

 

#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define pb push_back
#define mp make_pair
#define ULL unsigned long long
#define LL long long
#define inf 1e9
#define eps 1e-7
#define N 10009
using namespace std;
int m,n,T,t,q,k;
int need[20],ql,qr,e;
int ex[N<<2],lel[N<<2],minx[N<<2],lazy[N<<2];
/*
ex[o]:最大经验。没有加父节点的lazy[o].
lel[o]:最大水平。
minx[o]:区间升级所需最小的系数!(升级时才向下遍历-减小复杂度)
lazy[o]:区间增加的个数。
复杂度:大约O(kn+qlgn);
*/
void build(tree)
{
    lel[o]=1;
    ex[o]=lazy[o]=0;
    minx[o]=need[2];
    if(l<r)
    {
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
    }
}
void init()
{
    build(1,1,n);
    return ;
}
void pushup(int o)//只需更新父节点!
{
    ex[o]=max(ex[lo],ex[ro]);
    lel[o]=max(lel[lo],lel[ro]);
    minx[o]=min(minx[lo],minx[ro]);
}
void push_down(int o)//push_down时,修改子节点!更方便!
{
    if(lazy[o])
    {
        lazy[lo]+=lazy[o];
        lazy[ro]+=lazy[o];
        ex[lo]+=lazy[o]*lel[lo];
        ex[ro]+=lazy[o]*lel[ro];
        minx[lo]-=lazy[o];
        minx[ro]-=lazy[o];

        lazy[o]=0;
    }
}
void update(tree)
{
    if(l==r)
    {
        ex[o]+=lel[o]*(e);
        while(ex[o]>=need[lel[o]+1])lel[o]++;
        minx[o]=(need[lel[o]+1]-ex[o]+lel[o]-1)/lel[o];//+1
    }
    else
    {
        int mid=(l+r)>>1;
        if(ql<=l&&qr>=r)
        {
            if(minx[o]<=e)
            {
                push_down(o);
                if(ql<=mid)
                    update(lson);
                if(qr>mid)
                    update(rson);
                pushup(o);
            }
            else
            {
                ex[o]+=e*lel[o];
                lazy[o]+=e;
                minx[o]-=e;
            }
        }
        else
        {
            push_down(o);
            if(ql<=mid)
                update(lson);
            if(qr>mid)
                update(rson);
            pushup(o);
        }
    }
}
int query(tree)
{
    if(ql<=l&&qr>=r)
    {
        return ex[o];
    }
    else
    {
        push_down(o);
        int mid=(l+r)>>1;
        int ans=0;
        if(ql<=mid)ans=max(ans,query(lson));
        if(qr>mid)ans=max(ans,query(rson));
        pushup(o);
        return ans;
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int ncase=0;
    need[1]=0;
    scanf("%d",&T);
    char str[10];
    while(T--)
    {
        scanf("%d%d%d",&n,&k,&q);
        for(int i=2; i<=k; ++i)
            scanf("%d",&need[i]);
        need[k+1]=inf;
        init();
        printf("Case %d:\n",++ncase);
        while(q--)
        {
            scanf("%s",str);
            if(str[0]=='W')
            {
                scanf("%d%d%d",&ql,&qr,&e);
                update(1,1,n);
            }
            else
            {
                scanf("%d%d",&ql,&qr);
                printf("%d\n",query(1,1,n));
            }
        }
        puts("");
    }
    return 0;
}

 

 

 

posted @ 2013-10-14 21:48  baoff  阅读(215)  评论(0编辑  收藏  举报