[CodeVs4927]线段树练习5

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

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

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

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

代码如下:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long 
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{ll sum,max,min,delta1,delta2;int tag;}a[maxn*4];
ll n,m,x,y,z,tot;
char s[5];
void read(ll &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
void pushup(int x,int l,int r)
{
    if(l==r)return;
    a[x].sum=a[x<<1].sum+a[x<<1|1].sum;
    a[x].max=max(a[x<<1].max,a[x<<1|1].max);
    a[x].min=min(a[x<<1].min,a[x<<1|1].min);
}
void pushdown(int x,int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    if(a[x].tag==1)
    {
        a[x<<1].tag=a[x<<1|1].tag=1;a[x].tag=0;
        a[x<<1].sum=(mid-l+1)*a[x].delta2;a[x<<1|1].sum=(r-mid)*a[x].delta2;
        a[x<<1].max=a[x<<1|1].max=a[x<<1].min=a[x<<1|1].min=a[x].delta2;
        a[x<<1].delta2=a[x<<1|1].delta2=a[x].delta2;
        a[x<<1].delta1=a[x<<1|1].delta1=a[x].delta2=0;
    }
    if(a[x].delta1)
    {
        a[x<<1].delta1+=a[x].delta1;a[x<<1|1].delta1+=a[x].delta1;
        a[x<<1].sum+=a[x].delta1*(mid-l+1);a[x<<1|1].sum+=a[x].delta1*(r-mid);
        a[x<<1].max+=a[x].delta1;a[x<<1].min+=a[x].delta1;
        a[x<<1|1].max+=a[x].delta1;a[x<<1|1].min+=a[x].delta1;
        a[x].delta1=0;
    }
}
void build(int x,int l,int r)
{
    if(l==r){read(a[x].sum);a[x].max=a[x].min=a[x].sum;return;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    pushup(x,l,r);
}
void change(int x,int l,int r,int cl,int cr,int delta,int ty)
{
    pushdown(x,l,r);
    if(cl<=l&&r<=cr)
    {
        if(ty)
        {
            a[x].sum+=(r-l+1)*delta;
            a[x].delta1+=delta;
            a[x].max+=delta;
            a[x].min+=delta;
        }
        else
        {
            a[x].sum=(r-l+1)*delta;
            a[x].max=a[x].min=delta;
            a[x].delta1=0;a[x].delta2=delta;
            a[x].tag=1;
        }
        return;
    }
    int mid=(l+r)>>1;
    if(cl<=mid)change(x<<1,l,mid,cl,cr,delta,ty);
    if(cr>mid)change(x<<1|1,mid+1,r,cl,cr,delta,ty);
    pushup(x,l,r);
}
ll query(int x,int l,int r,int cl,int cr,int ty)
{
    pushdown(x,l,r);
    if(cl<=l&&r<=cr)
    {
        if(ty==1)return a[x].sum;
        if(ty==2)return a[x].max;
        return a[x].min;
    }
    int mid=(l+r)>>1;
    ll ret=0;
    if(ty==1)
    {
        if(cl<=mid)ret+=query(x<<1,l,mid,cl,cr,ty);
        if(cr>mid)ret+=query(x<<1|1,mid+1,r,cl,cr,ty);
    }
    if(ty==2)
    {
        ret=-inf;
        if(cl<=mid)ret=query(x<<1,l,mid,cl,cr,ty);
        if(cr>mid)ret=max(ret,query(x<<1|1,mid+1,r,cl,cr,ty));
    }
    if(ty==3)
    {
        ret=inf;
        if(cl<=mid)ret=query(x<<1,l,mid,cl,cr,ty);
        if(cr>mid)ret=min(ret,query(x<<1|1,mid+1,r,cl,cr,ty));
    }
    return ret;
}
int main()
{
    read(n);read(m);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);read(x);read(y);
        if(s[0]=='a')read(z),change(1,1,n,x,y,z,1);
        else if(s[0]=='s'&&s[1]=='e')read(z),change(1,1,n,x,y,z,0);
        else if(s[0]=='s'&&s[1]=='u')printf("%lld
",query(1,1,n,x,y,1));
        else if(s[0]=='m'&&s[1]=='a')printf("%lld
",query(1,1,n,x,y,2));
        else printf("%lld
",query(1,1,n,x,y,3));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Sakits/p/6411855.html