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分的用户表示诚挚的歉意

分类标签 Tags 点此展开 

 思路:区间赋值和区间加法综合操作。

先赋值,后加法。

注意:有一个全部赋值为0的情况。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100001
using namespace std;
int n,m;
struct nond{
    int l,r;
    long long sum,max,min;
    long long flag1,flag2;
}tree[MAXN*4];
void up(int now){
    tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;
    tree[now].min=min(tree[now*2].min,tree[now*2+1].min);
    tree[now].max=max(tree[now*2].max,tree[now*2+1].max);
}
void build(int now,int l,int r){
    tree[now].l=l;tree[now].r=r;
    tree[now].flag2=-1;
    if(tree[now].l==tree[now].r){
        scanf("%lld",&tree[now].sum);
        tree[now].min=tree[now].max=tree[now].sum;
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    up(now);
}
void down(int now){
    if(tree[now].flag2!=-1){
        tree[now*2].flag2=tree[now].flag2;
        tree[now*2+1].flag2=tree[now].flag2;
        tree[now*2].flag1=tree[now*2+1].flag1=0;
        tree[now*2].min=tree[now*2].max=tree[now].flag2;
        tree[now*2+1].min=tree[now*2+1].max=tree[now].flag2;
        tree[now*2].sum=(tree[now*2].r-tree[now*2].l+1)*tree[now].flag2;
        tree[now*2+1].sum=(tree[now*2+1].r-tree[now*2+1].l+1)*tree[now].flag2;
        tree[now].flag2=-1;
    }
    if(tree[now].flag1){
        tree[now*2].flag1+=tree[now].flag1;
        tree[now*2+1].flag1+=tree[now].flag1;
        tree[now*2].min+=tree[now].flag1;
        tree[now*2+1].min+=tree[now].flag1;
        tree[now*2].max+=tree[now].flag1;
        tree[now*2+1].max+=tree[now].flag1;
        tree[now*2].sum+=(tree[now*2].r-tree[now*2].l+1)*tree[now].flag1;
        tree[now*2+1].sum+=(tree[now*2+1].r-tree[now*2+1].l+1)*tree[now].flag1;
        tree[now].flag1=0;
    } 
}
void changeadd(int now,int l,int r,long long k){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].sum+=(tree[now].r-tree[now].l+1)*k;
        tree[now].min+=k;tree[now].max+=k;tree[now].flag1+=k;
        return ;
    }
    if(tree[now].flag1||tree[now].flag2!=-1)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    changeadd(now*2,l,r,k);
    else if(l>mid)    changeadd(now*2+1,l,r,k);
    else { changeadd(now*2,l,mid,k);changeadd(now*2+1,mid+1,r,k); }
    up(now);
}
void changeset(int now,int l,int r,long long k){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].min=k;tree[now].max=k;
        tree[now].flag1=0;tree[now].flag2=k;
        tree[now].sum=(tree[now].r-tree[now].l+1)*k;
        return ;
    }
    if(tree[now].flag1||tree[now].flag2!=-1)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    changeset(now*2,l,r,k);
    else if(l>mid)    changeset(now*2+1,l,r,k);
    else { changeset(now*2,l,mid,k);changeset(now*2+1,mid+1,r,k); }
    up(now);
}
long long querysum(int now,int l,int r){
    if(tree[now].l==l&&tree[now].r==r)
        return tree[now].sum;
    if(tree[now].flag1||tree[now].flag2!=-1)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    return querysum(now*2,l,r);
    else if(l>mid)    return querysum(now*2+1,l,r);
    else return querysum(now*2,l,mid)+querysum(now*2+1,mid+1,r); 
}
long long querymax(int now,int l,int r){
    if(tree[now].l==l&&tree[now].r==r)
        return tree[now].max;
    if(tree[now].flag1||tree[now].flag2!=-1)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    return querymax(now*2,l,r);
    else if(l>mid)    return querymax(now*2+1,l,r);
    else return max(querymax(now*2,l,mid),querymax(now*2+1,mid+1,r)); 
}
long long querymin(int now,int l,int r){
    if(tree[now].l==l&&tree[now].r==r)
        return tree[now].min;
    if(tree[now].flag1||tree[now].flag2!=-1)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    return querymin(now*2,l,r);
    else if(l>mid)    return querymin(now*2+1,l,r);
    else return min(querymin(now*2,l,mid),querymin(now*2+1,mid+1,r)); 
}
int main(){
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        char opt[10];int a,b;long long c;
        cin>>opt;scanf("%d%d",&a,&b);
        if(opt[0]=='a'){
            scanf("%lld",&c);
            changeadd(1,a,b,c);
        }
        else if(opt[0]=='s'&&opt[1]=='e'){
            scanf("%lld",&c);
            changeset(1,a,b,c);
        }
        else if(opt[0]=='s'&&opt[1]=='u')
            printf("%lld
",querysum(1,a,b));
        else if(opt[0]=='m'&&opt[1]=='a')
            printf("%lld
",querymax(1,a,b));
        else printf("%lld
",querymin(1,a,b));
    }
}
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/8537326.html