constintN(1e6 + 10);
int d[N];
template<classInfo>
structSegmentTree {
int n;
std::vector<Info> info;
SegmentTree() : n(0) {}
SegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
SegmentTree(std::vector<T> init_){
init(init_);
}
voidinit(int n_, Info v_ = Info()){
init(std::vector(n_, v_));
}
template<class T>
voidinit(std::vector<T> init_){
n = init_.size();
info.assign(4 << std::__lg(n), Info());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = Info(init_[l], init_[l]);
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
voidpull(int p){
info[p] = info[2 * p] + info[2 * p + 1];
}
voidrangeApply(int p, int l, int r, int x, int y){
if (l >= y or r <= x) {
return;
}
if (info[p].max == 2or info[p].max == 1) return ;//如果是2或者1就直接返回if (l >= x and r <= y and r - l == 1) {//直接修改即可 info[p].apply();
return;
}
int m = (l + r) / 2;
rangeApply(2 * p, l, m, x, y);
rangeApply(2 * p + 1, m, r, x, y);
pull(p);
}
voidrangeApply(int l, int r){
returnrangeApply(1, 0, n, l, r);
}
Info rangeQuery(int p, int l, int r, int x, int y){
if (l >= y || r <= x) {
returnInfo();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
returnrangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r){
returnrangeQuery(1, 0, n, l, r);
}
};
structInfo {
i64 max = -1;
i64 sum = 0;
Info(){}
Info(int _max, int _sum): max(_max), sum(_sum) {}
voidapply(){
max = d[max];
sum = d[sum];
}
};
Info operator+(Info a, Info b) {
Info c;
c.max = std::max(a.max, b.max);
c.sum = a.sum + b.sum;
return c;
}
voidpreprocessing(){//类似筛法原理,预处理出每个数的约数个数for (int i = 1; i <= N; ++i) {
for (int j = i; j <= N; j += i) {
d[j]++;
}
}
}
voidsolve(){
preprocessing();
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (auto& x : a) std::cin >> x;
SegmentTree<Info> T(a);
for (int i = 0; i < m; i++) {
int o, l, r;
std::cin >> o >> l >> r;
--l;
if (o == 1) {
T.rangeApply(l, r);
}
else {
std::cout << T.rangeQuery(l, r).sum << '\n';
}
}
}
4|2树状数组做法
用 set 维护每次需要处理的值,把当前的值小于等于 2 的都删除,然后树状数组暴力单点修改即可
template <typename T>
structFenwick {
int n;
std::vector<T> a;
Fenwick(int n_ = 0) {
init(n_);
}
voidinit(int n_){
n = n_;
a.assign(n, T{});
}
voidadd(int x, const T &v){
for (int i = x + 1; i <= n; i += i & -i) {
a[i - 1] = a[i - 1] + v;
}
}
T sum(int x){
T ans{};
for (int i = x; i > 0; i -= i & -i) {
ans = ans + a[i - 1];
}
return ans;
}
T rangeSum(int l, int r){
returnsum(r) - sum(l);
}
};
constint N = 1E6 + 10;
int d[N];
voidsolve(){
int n, m;
std::cin >> n >> m;
std::vector<i64> a(n);
for (auto& x : a) std::cin >> x;
for (int i = 1; i < N; i++) {
for (int j = i; j < N; j += i) {
d[j]++;
}
}
Fenwick<i64> T(n);
for (int i = 0; i < n; i++) {
T.add(i, a[i]);
}
std::set<i64> S;
for (int i = 0; i < n; i++) if (a[i] > 2) {
S.insert(i);
}
for (int i = 0; i < m; i++) {
int o, l, r;
std::cin >> o >> l >> r;
--l;
if (o == 1) {
autoit(S.lower_bound(l));
while(it != S.end()) {//带删除的迭代器遍历不能无脑++intidx(*it);
if (idx >= r) break;//因为[l, r),所以>=就得退出了 T.add(idx, -a[idx] + d[a[idx]]);
a[idx] = d[a[idx]];
if (a[idx] <= 2) {
it = S.erase(it);//删除后为了避免错乱,把当前迭代器改成删除后返回的迭代器//erase函数返回的是删除后的下一个元素的迭代器,所以不能++了 }
else {
it++;
}
}
}
else {
std::cout << T.rangeSum(l, r) << '\n';
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下