codevs 4927 线段树练习5

时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题目描述 Description

有n个数和5种操作

add a b c:把区间[a,b]内的所有数都增加c

set a b c:把区间[a,b]内的所有数都设为c

sum a b:查询区间[a,b]的区间和

max a b:查询区间[a,b]的最大值

min a b:查询区间[a,b]的最小值

输入描述 Input Description

第一行两个整数n,m,第二行n个整数表示这n个数的初始值

接下来m行操作,同题目描述

输出描述 Output Description

对于所有的sum、max、min询问,一行输出一个答案

样例输入 Sample Input

10 6

3 9 2 8 1 7 5 0 4 6

add 4 9 4

set 2 6 2

add 3 8 2

sum 2 10

max 1 7

min 3 6

 

样例输出 Sample Output

49

11

4

 

数据范围及提示 Data Size & Hint

10%:1<n,m<=10

30%:1<n,m<=10000

100%:1<n,m<=100000

保证中间结果在long long(C/C++)、int64(pascal)范围内

 

PS:由于数据6出错导致某些人只有90分,已于2016.5.13修正。

出题人在此对两位90分的用户表示诚挚的歉意

 

先下放set标记。。

屠龙宝刀点击就送

#include <cctype>
#include <cstdio>
#define N 100005
typedef long long LL;
inline void read(LL &x)
{
    bool f=0;register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=f?-x:x;
}
bool fst[N<<2|1];
int n,m,siz[N<<2|1];
LL ans,maxv[N<<2|1],minv[N<<2|1],fplus[N<<2|1],fset[N<<2|1],val[N<<2|1];
inline LL max(LL a,LL b) {return a>b?a:b;}
inline LL min(LL a,LL b) {return a>b?b:a;}
inline void pushup(int k)
{
    val[k]=val[k<<1]+val[k<<1|1];
    maxv[k]=max(maxv[k<<1],maxv[k<<1|1]);
    minv[k]=min(minv[k<<1],minv[k<<1|1]);
}
void build(int k,int l,int r)
{
    siz[k]=r-l+1;
    if(l==r)
    {
        read(val[k]);
        maxv[k]=minv[k]=val[k];
        return;
    }
    LL mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    pushup(k);
}
void pushdown1(int k)
{
    fplus[k<<1]=fplus[k<<1|1]=0;
    fset[k<<1]=fset[k<<1|1]=fset[k];
    maxv[k<<1]=minv[k<<1]=fset[k];
    maxv[k<<1|1]=minv[k<<1|1]=fset[k];
    val[k<<1]=siz[k<<1]*fset[k];
    val[k<<1|1]=siz[k<<1|1]*fset[k];
    fst[k<<1]=fst[k<<1|1]=1;
    fset[k]=0;fst[k]=0;
}
void pushdown2(int k)
{
    fplus[k<<1]+=fplus[k];
    fplus[k<<1|1]+=fplus[k];
    maxv[k<<1]+=fplus[k];
    maxv[k<<1|1]+=fplus[k];
    minv[k<<1]+=fplus[k];
    minv[k<<1|1]+=fplus[k];
    val[k<<1]+=fplus[k]*siz[k<<1];
    val[k<<1|1]+=fplus[k]*siz[k<<1|1];
    fplus[k]=0;
}
void modify(int k,int l,int r,int x,int y,LL v)
{
    if(l>=x&&r<=y)
    {
        val[k]+=siz[k]*v;
        maxv[k]+=v;
        minv[k]+=v;
        fplus[k]+=v;
        return;
    }
    int mid=(l+r)>>1;
    if(fst[k]) pushdown1(k);
    if(fplus[k]) pushdown2(k);
    if(x<=mid) modify(k<<1,l,mid,x,y,v);
    if(y>mid) modify(k<<1|1,mid+1,r,x,y,v);
    pushup(k);
}
void change(int k,int l,int r,int x,int y,LL v)
{
    if(l>=x&&r<=y)
    {
        val[k]=siz[k]*v;
        fplus[k]=0;
        maxv[k]=minv[k]=fset[k]=v;
        fst[k]=true;
        return;
    }
    int mid=(l+r)>>1;
    if(fst[k]) pushdown1(k);
    if(fplus[k]) pushdown2(k);
    if(x<=mid) change(k<<1,l,mid,x,y,v);
    if(y>mid) change(k<<1|1,mid+1,r,x,y,v);
    pushup(k);
}
void sum(int k,int l,int r,int x,int y)
{
    if(l>=x&&r<=y) {ans+=val[k];return;} 
    int mid=(l+r)>>1;
    if(fst[k]) pushdown1(k);
    if(fplus[k]) pushdown2(k);
    if(x<=mid) sum(k<<1,l,mid,x,y);
    if(y>mid) sum(k<<1|1,mid+1,r,x,y);
    pushup(k);
}
void Max(int k,int l,int r,int x,int y)
{
    if(l>=x&&r<=y) {ans=max(ans,maxv[k]);return;} 
    int mid=(l+r)>>1;
    if(fst[k]) pushdown1(k);
    if(fplus[k]) pushdown2(k);
    if(x<=mid) Max(k<<1,l,mid,x,y);
    if(y>mid) Max(k<<1|1,mid+1,r,x,y);
    pushup(k);
}
void Min(int k,int l,int r,int x,int y)
{
    if(l>=x&&r<=y) {ans=min(ans,minv[k]);return;}
    int mid=(l+r)>>1;
    if(fst[k]) pushdown1(k);
    if(fplus[k]) pushdown2(k);
    if(x<=mid) Min(k<<1,l,mid,x,y);
    if(y>mid) Min(k<<1|1,mid+1,r,x,y);
    pushup(k);
}
int main(int argc,char *argv[])
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    char opt[10];
    LL z;
    for(int x,y;m--;)
    {
        scanf("%s%d%d",opt,&x,&y);
        if(opt[0]=='a')
        {
            read(z);
            modify(1,1,n,x,y,z);
        }
        else if(opt[0]=='s')
        {
            if(opt[1]=='e') read(z),change(1,1,n,x,y,z);
            else ans=0,sum(1,1,n,x,y),printf("%lld\n",ans);
        }
        else if(opt[0]=='m')
        {
            if(opt[1]=='i') ans=1e18,Min(1,1,n,x,y),printf("%lld\n",ans);
            else ans=-1e18,Max(1,1,n,x,y),printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2017-10-21 08:14  杀猪状元  阅读(159)  评论(0编辑  收藏  举报