zoukankan      html  css  js  c++  java
  • 模板·双标记线段树

    又写了一遍线段树, 用了更多的模板元template, 实在是太方便了.对于我这种脑子不太灵活的选手很友好.
    不用纠结到底是int还是long long了.

    双标记线段树的主要注意的问题是如何合并标记.
    像这道题就是加的标记和乘的标记.
    线段树2
    什么?你说我的线段树跑的很慢?没问题呀, 考试的时候我又不这样写...

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    const int N = 500005;
    using namespace std;
    
    long long mod;
    template<typename Int>
    struct BaseNode {
        Int val, len, f1, f2;
        BaseNode *ls, *rs;
        BaseNode(Int _v = 0, BaseNode *_ls = nullptr, 
                 BaseNode *_rs = nullptr, Int _f1 = 1, Int _f2 = 0, Int _len = 0):
            val(_v), ls(_ls), rs(_rs), f1(_f1), f2(_f2), len(_len) { }
        void update() {
            val = (ls->val + rs->val) % mod;
            len = ls->len + rs->len;
        }
        void Merge(Int k1, Int k2) {
            f1 = f1 * k1 % mod, f2 = f2 * k1 % mod + k2,
            val = val * k1 % mod + k2 * len % mod,
            val %= mod, k1 %= mod, k2 %= mod;
        }
        template<typename Pair>
        void Merge(Pair P) {
            Merge(P.first, P.second);
        }
        void Down() {
            if (f1 or f2) ls->Merge(f1, f2), rs->Merge(f1, f2), f1 = 1, f2 = 0;
        }
        template<typename Integar>
        void F(Integar p) {
            val = p, len = 1;
        }
    };
    #define new_Node() new Node()
    
    template<typename Int>
    Int Merge(Int a, Int b) {
        return (a + b) % mod;
    }
    
    template<typename Node, typename Int>
    class Tree {
        int n;
        Node *root;
    #define LS l, mid, node->ls
    #define RS mid + 1, r, node->rs
        template<typename Integar>
        void build(int l, int r, Node *node, Integar *A) {
            if (l == r) 
                return node->F(A[l]);
            int mid = l + r >> 1;
            node->ls = new_Node();
            node->rs = new_Node();
            build(LS, A), build(RS, A);
            node->update();
        }
        template<typename STRUCT>
        void addition(int l, int r, Node *node, int L, int R, STRUCT k) {
            if (l >= L and r <= R)
                return node->Merge(k);
            node->Down();
            int mid = l + r >> 1;
            if (L <= mid) addition(LS, L, R, k);
            if (R >  mid) addition(RS, L, R, k);
            node->update();
        }
        Int Query(int l, int r, Node *node, int L, int R) {
            if (l >= L and r <= R)
                return node->val;
            node->Down();
            int mid = l + r >> 1;
            Int res = 0;
            if (L <= mid) res = Merge(res, Query(LS, L, R));
            if (R >  mid) res = Merge(res, Query(RS, L, R));
            return res;
        }
      public:
        Tree(int _n) : n(_n), root(new_Node()) {}
        template<typename Integar>
        void build(Integar *A) {
            build(1, n, root, A);
        }
        template<typename STRUCT>
        void addition(int L, int R, STRUCT k) {
            addition(1, n, root, L, R, k);
        }
        Int Query(int L, int R) {
            return Query(1, n, root, L, R);
        }
    };
    
    int A[N];
    int main () {
        int n, m;
        scanf("%d%d%d", &n, &m, &mod);
        Tree<BaseNode<long long>, long long>* T = 
            new Tree<BaseNode<long long>, long long>(n);
        for (int i = 1; i <= n; i += 1) scanf("%d", &A[i]);
        T->build(A);
        while (m--) {
            int opt, x, y, k;
            scanf("%d%d%d", &opt, &x, &y);
            if (opt == 1) {
                scanf("%d", &k);
                T->addition(x, y, make_pair(k, 0));
            } else if (opt == 2) {
                scanf("%d", &k);
                T->addition(x, y, make_pair(1, k));
            } else {
                printf("%lld
    ", T->Query(x, y));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    log4net简介(四)
    Log4net简介(二)
    详解制作集成SP2的Windows2003安装光盘
    给Fedora11安装声卡驱动
    CSS背景色的半透明设置
    利用事务日志来误操作恢复与灾难恢复
    log4net简介(三)之无法写入日志
    能盖住Select的Div
    SQLServer将日期转换成字符串格式
    如何在 Windows 恢复环境中使用 Bootrec.exe 工具解决和修复 Windows Vista 中的启动问题
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/9925877.html
Copyright © 2011-2022 走看看