首页 > 其他分享 >【学习笔记/模板】吉司机线段树

【学习笔记/模板】吉司机线段树

时间:2022-09-22 21:58:03浏览次数:90  
标签:rt lazy int max 线段 tr 笔记 st 模板

吉司机线段树

这里不会挂涩图了,相册或者公告板自取

调了一晚上,刚改出来,有时间再更。

P6242 【模板】线段树 3

Code

#include<cstdio>
#include<algorithm>

#define LL long long

using namespace std;

const LL INF = 1e18;
const int MAXN = 5e5 + 10;
int n, m;
LL num[MAXN];

inline LL read(){
    LL x = 0, f = 1;
    char c = getchar();

    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }

    return x * f;
}

struct Segment_Tree{
    struct Tree{
        int l, r;
        LL sum;
        LL max_st, max_nd, max_his; //分别是:区间最大值,严格区间次大值,区间最大值的个数
        LL num_max;
        LL lazy_st, lazy_sth, lazy_nd, lazy_ndh;
        //分别是:最大值加减标记,最大值历史最大的加减标记
        //       非最大值加减标记,非最大值历史最大的加减标记
    }tr[MAXN << 2];

    inline int lson(int rt){
        return rt << 1;
    }

    inline int rson(int rt){
        return rt << 1 | 1;
    }

    inline void Pushup(int rt){
        tr[rt].sum = tr[lson(rt)].sum + tr[rson(rt)].sum;
        tr[rt].max_st = max(tr[lson(rt)].max_st, tr[rson(rt)].max_st);
        tr[rt].max_his = max(tr[lson(rt)].max_his, tr[rson(rt)].max_his);

        if(tr[lson(rt)].max_st == tr[rson(rt)].max_st){
            tr[rt].num_max = tr[lson(rt)].num_max + tr[rson(rt)].num_max;
            tr[rt].max_nd = max(tr[lson(rt)].max_nd, tr[rson(rt)].max_nd);
        }
        else if(tr[lson(rt)].max_st > tr[rson(rt)].max_st){
            tr[rt].num_max = tr[lson(rt)].num_max;
            tr[rt].max_nd = max(tr[lson(rt)].max_nd, tr[rson(rt)].max_st);
        }
        else if(tr[lson(rt)].max_st < tr[rson(rt)].max_st){
            tr[rt].num_max = tr[rson(rt)].num_max;
            tr[rt].max_nd = max(tr[lson(rt)].max_st, tr[rson(rt)].max_nd);
        }
    }

    void Build(int rt, int l, int r){
        tr[rt].l = l;
        tr[rt].r = r;

        if(l == r){
            tr[rt].sum = tr[rt].max_st = tr[rt].max_his = num[l];
            tr[rt].num_max = 1;
            tr[rt].max_nd = -INF;

            return;
        }

        int mid = (l + r) >> 1;
        Build(lson(rt), l, mid);
        Build(rson(rt), mid + 1, r);

        Pushup(rt);
    }

    inline void Modify(int rt, LL val_st, LL val_sth, LL val_nd, LL val_ndh){
        tr[rt].sum += (tr[rt].num_max * val_st + (tr[rt].r - tr[rt].l + 1 - tr[rt].num_max) * val_nd);
        tr[rt].max_his = max(tr[rt].max_his, tr[rt].max_st + val_sth);
        tr[rt].max_st += val_st;

        if(tr[rt].max_nd != -INF) tr[rt].max_nd += val_nd;

        tr[rt].lazy_sth = max(tr[rt].lazy_sth, tr[rt].lazy_st + val_sth);
        tr[rt].lazy_st += val_st;
        tr[rt].lazy_ndh = max(tr[rt].lazy_ndh, tr[rt].lazy_nd + val_ndh);
        tr[rt].lazy_nd += val_nd;
    }

    inline void Pushdown(int rt){
        int maxn = max(tr[lson(rt)].max_st, tr[rson(rt)].max_st);

        if(tr[lson(rt)].max_st == maxn)
            Modify(lson(rt), tr[rt].lazy_st, tr[rt].lazy_sth, tr[rt].lazy_nd, tr[rt].lazy_ndh);
        else Modify(lson(rt), tr[rt].lazy_nd, tr[rt].lazy_ndh, tr[rt].lazy_nd, tr[rt].lazy_ndh);

        if(tr[rson(rt)].max_st == maxn)
            Modify(rson(rt), tr[rt].lazy_st, tr[rt].lazy_sth, tr[rt].lazy_nd, tr[rt].lazy_ndh);
        else Modify(rson(rt), tr[rt].lazy_nd, tr[rt].lazy_ndh, tr[rt].lazy_nd, tr[rt].lazy_ndh);

        tr[rt].lazy_st = 0, tr[rt].lazy_sth = 0, tr[rt].lazy_nd = 0, tr[rt].lazy_ndh = 0;
    }

    void Update_Add(int rt, int l, int r, LL val){
        if(tr[rt].l >= l && tr[rt].r <= r){
            Modify(rt, val, val, val, val);
            return;
        }

        Pushdown(rt);

        int mid = (tr[rt].l + tr[rt].r) >> 1;
        if(l <= mid) Update_Add(lson(rt), l, r, val);
        if(r > mid) Update_Add(rson(rt), l, r, val);

        Pushup(rt);
    }

    void Update_Min(int rt, int l, int r, LL val){
        if(tr[rt].max_st <= val) return;

        if(tr[rt].l >= l && tr[rt].r <= r && tr[rt].max_nd < val){
            Modify(rt, val - tr[rt].max_st, val - tr[rt].max_st, 0, 0);
            return;
        }

        Pushdown(rt);

        int mid = (tr[rt].l + tr[rt].r) >> 1;
        if(l <= mid) Update_Min(lson(rt), l, r, val);
        if(r > mid) Update_Min(rson(rt), l, r, val);

        Pushup(rt);
    }

    LL Query_Sum(int rt, int l, int r){
        if(tr[rt].l >= l && tr[rt].r <= r)
            return tr[rt].sum;
        
        Pushdown(rt);

        LL ans = 0;
        int mid = (tr[rt].l + tr[rt].r) >> 1;
        if(l <= mid) ans += Query_Sum(lson(rt), l, r);
        if(r > mid) ans += Query_Sum(rson(rt), l, r);

        return ans;
    }

    LL Query_Max(int rt, int l, int r){
        if(tr[rt].l >= l && tr[rt].r <= r)
            return tr[rt].max_st;
        
        Pushdown(rt);

        LL ans = -INF;
        int mid = (tr[rt].l + tr[rt].r) >> 1;
        if(l <= mid) ans = max(ans, Query_Max(lson(rt), l, r));
        if(r > mid) ans = max(ans, Query_Max(rson(rt), l, r));

        return ans;
    }

    LL Query_His(int rt, int l, int r){
        if(tr[rt].l >= l && tr[rt].r <= r)
            return tr[rt].max_his;

        Pushdown(rt);

        LL ans = -INF;
        int mid = (tr[rt].l + tr[rt].r) >> 1;
        if(l <= mid) ans = max(ans, Query_His(lson(rt), l, r));
        if(r > mid) ans = max(ans, Query_His(rson(rt), l, r));

        return ans;
    }
}S;

int main(){
    n = read(), m = read();
    for(register int i = 1; i <= n; i++)
        num[i] = read();
    
    S.Build(1, 1, n);

    for(register int i = 1; i <= m; i++){
        int opt;
        opt = read();

        if(opt == 1){
            int l, r, k;
            l = read(), r = read(), k = read();
            S.Update_Add(1, l, r, k);
        }
        else if(opt == 2){
            int l, r, v;
            l = read(), r = read(), v = read();
            S.Update_Min(1, l, r, v);
        }
        else if(opt == 3){
            int l, r;
            l = read(), r = read();
            printf("%lld\n", S.Query_Sum(1, l, r));
        }
        else if(opt == 4){
            int l, r;
            l = read(), r = read();
            printf("%lld\n", S.Query_Max(1, l, r));
        }
        else{
            int l, r;
            l = read(), r = read();
            printf("%lld\n", S.Query_His(1, l, r));
        }
    }

    return 0;
}

标签:rt,lazy,int,max,线段,tr,笔记,st,模板
From: https://www.cnblogs.com/TSTYFST/p/16720977.html

相关文章

  • IDEA 使用笔记
    快捷键SearchEverywhere:双击Shift快捷键说明ctrl+P列出参数列表(使用比较多)ctrl+shift+enter当在括号里输入完最后一个参数时候他会直接光标跳......
  • Flask学习笔记(二)-request请求对象+flask解析http请求数据
    一、flask请求对象requestrequest是flask框架的全局对象,你可以通过它来获得当前进入的请求数据,如果是在多线程环境下,flask可以保证你所使用的request对象就是当前这个线程......
  • Python面向对象笔记
    一、面向对象(一)基本概念(1)面向对象编程——ObjectOrientedProgramming简写OOP(2)面向对象三大特性封装根据职责将属性和方法封装到一个抽象的类中定......
  • Python基础笔记(全)
    零、python前言(一)解释器计算机不能直接理解任何除机器语言以外的语言,必须要把程序语言翻译成机器语言,计算机才能执行程序。编译器:将其他语言翻译成机器语言的工具编译......
  • JavaScript学习笔记 第七章 原型
    原型prototypefunctionPerson(){}Person.prototype.a=123;varper=newPerson();//console.log(per.prototype);//conso......
  • 数据库事务处理中ACID之I隔离性处理笔记
    隔离性要求要求并发执行的事务之间互相隔离,互不影响但是并发程序可能会两个程序尝试同时读或者一个正在读一个正在写,这些都可能出现问题,于是数据库通过隔离性来避免这些......
  • Python学习笔记2(未完待续)
      使用占位符格式化字符串:使用占位符格式化输出时:在%后面加数字表示给这个字符多少个位置,不足电脑会自动使用空格补齐。正数表示左对齐,负数表示右对齐。如:%4d表示左对......
  • vue学习笔记(三):axios获得远程数据,拦截器
     安装:npmiaxios 请求数据代码如下:<script>importaxiosfrom'axios';exportdefault{data:()=>{return{name:''},methods:{set_val(){......
  • 基础知识笔记(VIM)
    一、VI/VIM编辑器(重要)1.1是什么VI是Unix操作系统和类Unix操作系统中最通用的文本编辑器。VIM编辑器是从VI发展出来的一个性能更强大的文本编辑器。可以......
  • Tita 360度评估——员工通用胜任力测评问卷模板
    360评估指导语本次员工职业领导力素质测评由Tita360评估全程在线支持。Tita「360 评估」,申请试用请联系售前/售后顾问,或者直接在线预约演示本问卷通过对被评价者的......