首页 > 其他 > 详细

[CodeVs4927]线段树练习5

时间:2017-02-18 00:57:46      阅读:189      评论:0      收藏:0      [点我收藏+]

  。。。调了三个晚上的模板题,各种千奇百怪的错误全都出现过了一遍QWQ

  题目大意:区间增减(add),区间修改为一个数(set),区间求和(sum),区间最大值(max),区间最小值(min)。

  tips:set优先级大于add,一个节点进行set操作要将add的lazy清除,一个结点进行add操作要将set的lazy下传,对于一个结点set和add的lazy不能同时存在,查询的时候先下传set的lazy再下传add的lazy。

  好像codevs的评测姬有点奇怪,本地开四倍不会RE,评测姬会,只好开八倍了QAQ

代码如下:

技术分享
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
struct poi{int x,l,r;long long sum,delta1,delta2,max,min;bool en;}a[810000];
int n,m;
long long x,y,z;
char ch[100];
long long calcsum(int x){return a[x].en?a[x].delta1*(a[x].r-a[x].l+1):a[x].sum+a[x].delta2*(a[x].r-a[x].l+1);}
long long calcmax(int x){return a[x].en?a[x].delta1:a[x].max+a[x].delta2;}
long long calcmin(int x){return a[x].en?a[x].delta1:a[x].min+a[x].delta2;}
void build(int x,int l,int r)
{
    a[x].l=l;a[x].r=r;a[x].en=a[x].delta1=a[x].delta2=0;
    if(l==r)scanf("%lld",&a[x].sum),a[x].max=a[x].min=a[x].sum;
    else
    {
        build(x*2,l,(l+r)>>1);build(x*2+1,((l+r)>>1)+1,r);
        a[x].sum=a[x*2].sum+a[x*2+1].sum;
        a[x].max=max(a[x*2].max,a[x*2+1].max);
        a[x].min=min(a[x*2].min,a[x*2+1].min);
    }
}
void down1(int x)
{
    a[x*2].en=a[x*2+1].en=1;a[x*2].delta1=a[x*2+1].delta1=a[x].delta1;
    a[x].max=calcmax(x);a[x].min=calcmin(x);a[x].sum=calcsum(x);a[x].en=0;
    a[x*2].delta2=a[x*2+1].delta2=0;
}
void down2(int x)
{
    a[x].sum+=a[x].delta2*(a[x].r-a[x].l+1);a[x].max+=a[x].delta2;a[x].min+=a[x].delta2;
    if(a[x*2].en)down1(x*2);if(a[x*2+1].en)down1(x*2+1);
    a[x*2].delta2+=a[x].delta2;a[x*2+1].delta2+=a[x].delta2;a[x].delta2=0;
}
void update1(int x,int l,int r,long long delta)
{
    if(a[x].en&&a[x].l)down1(x);
    if(l<=a[x].l&&a[x].r<=r)a[x].en=1,a[x].delta1=delta,a[x].delta2=0,a[x].sum=a[x].delta1*(a[x].r-a[x].l+1);
    else
    {
        if(a[x].delta2)down2(x);
        if(l<=(a[x].l+a[x].r)>>1)update1(x*2,l,r,delta);
        if(r>(a[x].l+a[x].r)>>1)update1(x*2+1,l,r,delta);
        a[x].sum=calcsum(x*2)+calcsum(x*2+1);
        a[x].max=max(calcmax(x*2),calcmax(x*2+1));
        a[x].min=min(calcmin(x*2),calcmin(x*2+1));
    }
}
void update2(int x,int l,int r,long long delta)
{
    if(a[x].en&&a[x].l)down1(x);
    if(l<=a[x].l&&a[x].r<=r)a[x].delta2+=delta;
    else
    {
        if(a[x].delta2)down2(x);
        if(l<=(a[x].l+a[x].r)>>1)update2(x*2,l,r,delta);
        if(r>(a[x].l+a[x].r)>>1)update2(x*2+1,l,r,delta);
        a[x].sum=calcsum(x*2)+calcsum(x*2+1);
        a[x].max=max(calcmax(x*2),calcmax(x*2+1));
        a[x].min=min(calcmin(x*2),calcmin(x*2+1));
    }
}
long long querysum(int x,int l,int r)
{
    long long ret=0;
    if(l<=a[x].l&&a[x].r<=r)ret=calcsum(x);
    else
    {
        if(a[x].en&&a[x].l)down1(x);
        if(a[x].delta2)down2(x);
        if(l<=(a[x].l+a[x].r)>>1)ret+=querysum(x*2,l,r);
        if(r>(a[x].l+a[x].r)>>1)ret+=querysum(x*2+1,l,r);
    }
    return ret;
}
long long querymax(int x,int l,int r)
{
    long long ret=-100000000;
    if(l<=a[x].l&&a[x].r<=r)ret=calcmax(x);
    else
    {
        if(a[x].en&&a[x].l)down1(x);
        if(a[x].delta2)down2(x);
        if(l<=(a[x].l+a[x].r)>>1)ret=max(ret,querymax(x*2,l,r));
        if(r>(a[x].l+a[x].r)>>1)ret=max(ret,querymax(x*2+1,l,r));
    }
    return ret;
}
long long querymin(int x,int l,int r)
{
    long long ret=100000000;
    if(l<=a[x].l&&a[x].r<=r)ret=calcmin(x);
    else
    {
        if(a[x].en&&a[x].l)down1(x);
        if(a[x].delta2)down2(x);
        if(l<=(a[x].l+a[x].r)>>1)ret=min(ret,querymin(x*2,l,r));
        if(r>(a[x].l+a[x].r)>>1)ret=min(ret,querymin(x*2+1,l,r));
    }
    return ret;
}
int main()
{
    scanf("%d %d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        getchar();
        scanf("%s",ch);
        if(ch[0]==a)
        {
            scanf("%lld %lld %lld",&x,&y,&z);
            update2(1,x,y,z);
        }
        if(ch[1]==e)
        {
            scanf("%lld %lld %lld",&x,&y,&z);
            update1(1,x,y,z);
        }
        if(ch[1]==u)
        {
            scanf("%lld %lld",&x,&y);
            printf("%lld\n",querysum(1,x,y));
        }
        if(ch[1]==a)
        {
            scanf("%lld %lld",&x,&y);
            printf("%lld\n",querymax(1,x,y));
        }
        if(ch[1]==i)
        {
            scanf("%lld %lld",&x,&y);
            printf("%lld\n",querymin(1,x,y));
        }
    }
}
View Code

 

[CodeVs4927]线段树练习5

原文:http://www.cnblogs.com/Sakits/p/6411855.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!