zoukankan      html  css  js  c++  java
  • CF920F 【SUM and REPLACE】

    题面

    题意:

    1:将 [l,r]区间内的所有数变为当前权值的正约数的个数,即:(a_i)=d(a_i)

    2:求(displaystyle sum_{i=l}^{r}a_{i})

    前置芝士:

    (d(i))的话,可以先康康这个题P6810 「MCOI-02」Convex Hull 凸包

    这个题中就是线性筛处理出了每个数的约数的个数

    这里安利一个同机房dalao的博客

    我们就可以发现每个数的约数的个数就可以处理出来了

    void make_d(){
        d[1] = f[1] = 1;
        for(int i = 2; i <= M - 5; i ++){
            if(!is_pri[i]){
                pri[++ cnt] = i;
                f[i] = 1;
                d[i] = 2;
            }
            for(int j = 1; j <= cnt && i * pri[j] <= M - 5; j ++){
                is_pri[i * pri[j]] = 1;
                if(i % pri[j] == 0){
                    f[i * pri[j]] = f[i] + 1;
                    d[i * pri[j]] = (d[i]) * (f[i * pri[j]] + 1) / (f[i] + 1);
                    break;
                }
                f[i * pri[j]] = 1;
                d[i * pri[j]] = d[i] * d[pri[j]];
            }
        }
    }
    

    实现:

    我们先用线性筛筛出每个数的约数的个数

    然后维护一棵线段树,线段树维护一个区间(sum)和区间最大值

    我们考虑当(i=1或2)的时候,(d(i))是等于(i)的,所以不用修改

    所以当区间最大值(<=2)的时候,我们就可以不对这个区间进行任何修改操作了(因为操作了也没有任何意义)

    然后就是维护一棵普通的线段树就好了

    但是这个题要注意开$long long $,不然会炸的

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ls(o) (o << 1)
    #define rs(o) (o << 1 | 1)
    #define mid ((l + r) >> 1)
    const int N = 3e5 + 5, M = 1e6 + 5;
    int n, m, a[N], pri[N], cnt;
    long long mx[N << 2], tr[N << 2], d[M], f[M];
    bool is_pri[M];
    void make_d(){
        d[1] = f[1] = 1;
        for(int i = 2; i <= M - 5; i ++){
            if(!is_pri[i]){
                pri[++ cnt] = i;
                f[i] = 1; d[i] = 2;
            }
            for(int j = 1; j <= cnt && i * pri[j] <= M - 5; j ++){
                is_pri[i * pri[j]] = 1;
                if(i % pri[j] == 0){
                    f[i * pri[j]] = f[i] + 1;
                    d[i * pri[j]] = (d[i]) * (f[i * pri[j]] + 1) / (f[i] + 1);
                    break;
                }
                f[i * pri[j]] = 1;
                d[i * pri[j]] = d[i] * d[pri[j]];
            }
        }
    }
    void up(int o){
        tr[o] = tr[ls(o)] + tr[rs(o)];
        mx[o] = max(mx[ls(o)], mx[rs(o)]);
    }
    void build(int o, int l, int r){
        if(l == r){
            scanf("%d", &tr[o]);
            mx[o] = tr[o];
            return ;
        }
        build(ls(o), l, mid); build(rs(o), mid + 1, r);
        up(o);
    }
    void change(int o, int l, int r, int L, int R){
        if(mx[o] <= 2) return ;
        if(l == r){
            tr[o] = mx[o] = d[tr[o]];
            return ;
        }
        if(L <= mid) change(ls(o), l, mid, L, R);
        if(R > mid) change(rs(o), mid + 1, r, L, R);
        up(o);
    }
    long long query(int o, int l, int r, int L, int R){
        if(L <= l && r <= R) return tr[o];
        long long res = 0;
        if(L <= mid) res += query(ls(o), l, mid, L, R);
        if(R > mid) res += query(rs(o), mid + 1, r, L, R);
        return res; 
    }
    int main(){
        scanf("%d %d", &n, &m);
        make_d(); build(1, 1, n);
        for(int i = 1, opt, l, r; i <= m; i ++){
            scanf("%d %d %d", &opt, &l, &r);
            if(opt == 1) change(1, 1, n, l, r);
            else printf("%lld
    ", query(1, 1, n, l, r));
        }
        return 0;
    }
    

    完美撒花✿✿ヽ(°▽°)ノ✿

  • 相关阅读:
    Leetcode——栈和队列(3)
    Leetcode——栈和队列(2)
    java——面试题 基础(上)
    Leetcode——栈和队列(1)
    LeetCode——动态规划整理(2)
    LeetCode——动态规划整理(1)
    计算机网络——数据中心(下)
    计算机网络——数据中心(上)
    计算机网络——HTTP(下)
    计算机网络——HTTP(上)
  • 原文地址:https://www.cnblogs.com/wsdslll/p/13710175.html
Copyright © 2011-2022 走看看