模板·双标记线段树
又写了一遍线段树, 用了更多的模板元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\n", T->Query(x, y));
}
}
return 0;
}
为什么要过别人为我安排的生活.