• 4927 线段树练习5 (多重标记下放)


    题目描述 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)范围内

    思路;

    有两个标记一个add一个set,我们肯定是优先处理set操作,如果当前点被set标记了,那么之前的add标记也会被清空,所以当进行set操作是必须要清空add标记。

    题目没给 c 的范围,那么我们假定他为 -1e9 < c < 1e9 ,那么也就是有可能存在等于0和负数的情况,所以set标记的初始化可以选定为 -1e16;

    为社么感觉写过。。。

    实现代码;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid ll m = (l + r) >> 1
    const ll M = 1e5 + 10;
    const ll inf = 1e16+10;
    ll sum[M<<2],Set[M<<2],mx[M<<2],add[M<<2],mn[M<<2];
    ll a[M];
    void pushup(ll rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        mx[rt] = max(mx[rt<<1],mx[rt<<1|1]);
        mn[rt] = min(mn[rt<<1],mn[rt<<1|1]);
    }
    
    void pushdown(ll l,ll r,ll rt){
        if(Set[rt]!=-inf){
            mid;
            sum[rt<<1] = Set[rt]*(m-l+1);
            sum[rt<<1|1] = Set[rt]*(r-m);
            mx[rt<<1] = mx[rt<<1|1] = Set[rt];
            mn[rt<<1] = mn[rt<<1|1] = Set[rt];
            Set[rt<<1] = Set[rt<<1|1] = Set[rt];
            add[rt<<1] = add[rt<<1|1] = 0;
            Set[rt] = -inf;
        }
        if(add[rt]){
            mid;
            sum[rt<<1] += add[rt]*(m-l+1);
            sum[rt<<1|1] += add[rt]*(r-m);
            mx[rt<<1] += add[rt]; mx[rt<<1|1] += add[rt];
            mn[rt<<1] += add[rt]; mn[rt<<1|1] += add[rt];
            add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt];
            add[rt] = 0;
        }
    }
    
    void build(ll l,ll r,ll rt){
        Set[rt] = -inf; add[rt] = 0;
        if(l == r){
            sum[rt] = mx[rt] = mn[rt] = a[l];
            Set[rt] = -inf;add[rt] = 0;
            return ;
        }
        mid;
        build(lson); build(rson);
        pushup(rt);
    }
    
    void update(ll L,ll R,ll op,ll c,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
             if(op == 1){
                 sum[rt] = (r-l+1)*c;
                 mx[rt] = mn[rt] = Set[rt] = c;
                 add[rt] = 0;
                 return ;
             }
             else{
                sum[rt] += (r-l+1)*c;
                mx[rt] += c; add[rt] += c;
                mn[rt] += c;
                return ;
             }
        }
        pushdown(l,r,rt);
        mid;
        if(L <= m) update(L,R,op,c,lson);
        if(R > m) update(L,R,op,c,rson);
        pushup(rt);
    }
    
    ll query_sum(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        pushdown(l,r,rt);
        mid; ll ret = 0;
        if(L <= m) ret += query_sum(L,R,lson);
        if(R > m) ret += query_sum(L,R,rson);
        return ret;
    }
    
    ll query_max(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return mx[rt];
        }
        pushdown(l,r,rt);
        mid; ll ret = -inf;
        if(L <= m) ret = max(ret,query_max(L,R,lson));
        if(R > m) ret = max(ret,query_max(L,R,rson));
        return ret;
    }
    
    ll query_min(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return mn[rt];
        }
        pushdown(l,r,rt);
        mid,ret = inf;
        if(L <= m) ret = min(ret,query_min(L,R,lson));
        if(R > m) ret = min(ret,query_min(L,R,rson));
        return ret;
    }
    
    char s[100];
    int main(){
        ll n,l,r,c,q;
        scanf("%lld%lld",&n,&q);
        for(ll i = 1;i <= n;i ++)
            scanf("%lld",&a[i]);
        build(1,n,1);
        while(q--){
            scanf("%s",s); scanf("%lld%lld",&l,&r);
            if(s[0] == 'a'){
                scanf("%lld",&c);
                update(l,r,0,c,1,n,1);
            }
            else if(s[0] == 's'&&s[1] == 'e'){
                scanf("%lld",&c);
                update(l,r,1,c,1,n,1);
            }
            else if(s[0] == 's'&&s[1] == 'u'){
                 printf("%lld
    ",query_sum(l,r,1,n,1));
            }
            else if(s[0] == 'm'&&s[1] == 'a'){
                printf("%lld
    ",query_max(l,r,1,n,1));
            }
            else {
                printf("%lld
    ",query_min(l,r,1,n,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    The Water Problem HDU-5443
    约瑟夫环1
    迪杰斯特拉算法1 HDU-1874
    [20200729NOIP提高组模拟T2]学数数——坎坷
    [20200728NOIP提高组模拟T4]有趣的有趣的家庭菜园——自闭了
    [20200728NOIP提高组模拟T1]Copy
    [20200728NOIP提高组模拟T2]愉快的logo设计
    [20200727NOIP提高组模拟T3]计算几何
    [20200727NOIP提高组模拟T2]走路
    [CQOI2015]任务查询系统
  • 原文地址:https://www.cnblogs.com/kls123/p/9898654.html
Copyright © 2020-2023  润新知