第 446 场周赛——求出数组的 X 值 II
题目
题解
用到线段树确实忘完了,这里用的是灵神的板子,只需要根据题意修改即可。
参考代码
class SegmentTree { //线段树板子
using T = pair<int, array<int, 5>>; //这里可以template<typename T>在一开始定义,也可以这样在这里定义
int k;
int n;
vector<T> tree;
T merge_val(T a, T b) const{ //合并两个val,视题目而改变
auto [left_mul, cnt] = a;
for(int rx = 0; rx < k; rx++) {
cnt[left_mul * rx % k] += b.second[rx];
}
return {left_mul * b.first % k, cnt};
}
T new_val(int val) const { //更新单个节点
int mul = val % k;
array<int, 5> cnt{};
cnt[mul] = 1;
return {mul, cnt};
}
void maintain(int node) { //合并左右儿子的val到当前节点
tree[node] = merge_val(tree[node * 2], tree[node * 2 + 1]);
}
void build(const vector<int>& a, int node, int l, int r) { //初始化线段树
if(l == r) {
tree[node] = new_val(a[l]);
return;
}
int m = (l + r) / 2;
build(a, node * 2, l, m);
build(a, node * 2 + 1, m + 1, r);
maintain(node);
}
void update(int node, int l, int r, int i, int val) { //更新线段树中某个元素的值
if(l == r) {
tree[node] = new_val(val);
return;
}
int m = (l + r) / 2;
if(i <= m) {
update(node * 2, l, m, i, val);
} else {
update(node * 2 + 1, m + 1, r, i, val);
}
maintain(node);
}
T query(int node, int l, int r, int ql, int qr) const {
if(ql <= l && r <= qr) {
return tree[node];
}
int m = (l + r) / 2;
if(qr <= m) {
return query(node * 2, l, m, ql, qr);
}
if(ql > m) {
return query(node * 2 + 1, m + 1, r, ql, qr);
}
T l_res = query(node * 2, l, m, ql, qr);
T r_res = query(node * 2 + 1, m + 1, r, ql, qr);
return merge_val(l_res, r_res);
}
public:
SegmentTree(const vector<int>& a, int k) : k(k), n(a.size()), tree(2 << bit_width(a.size() - 1)) { //:后面为初始化的内容
build(a, 1, 0, n - 1);
}
void update(int i, int val) {
update(1, 0, n - 1, i, val);
}
T query(int ql, int qr) const {
return query(1, 0, n - 1, ql, qr);
}
};
class Solution {
public:
vector<int> resultArray(vector<int>& nums, int k, vector<vector<int>>& queries) {
SegmentTree t(nums, k);
int n = nums.size();
vector<int> ans;
for(auto& q : queries) {
t.update(q[0], q[1]);
auto [_, cnt] = t.query(q[2], n - 1);
ans.push_back(cnt[q[3]]);
}
return ans;
}
};

浙公网安备 33010602011771号