又寫了一遍線段樹, 用了更多的模板元template
, 實在是太方便了.對於我這種腦子不太靈活的選手很友好.
不用糾結究竟是int仍是long long了.node
雙標記線段樹的主要注意的問題是如何合併標記.
像這道題就是加的標記和乘的標記.
線段樹2
什麼?你說個人線段樹跑的很慢?沒問題呀, 考試的時候我又不這樣寫...ios
#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\n", T->Query(x, y)); } } return 0; }