F. SUM and REPLACE

跟風遠走 提交于 2020-03-11 14:48:36

F. SUM and REPLACE

题意

定义D数组为一个数的约数个数 ,接下来有两种操作

1操作对于区间[l,r],将al-ar用D(ai)替代。

2操作求区间和。

思路

此题有一个小技巧就是:1e6以内的数都可以在6次求约数个数操作内变为2和1 ,而且1e6以内的最大因字数。

而2的因子个数是2,1的因子个数是1,如果需要更新的位置 所存的数 <=2则就不需要更新了 。

代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+10;
ll s[4*maxn];//存放因子个数
ll sum[4*maxn];//存放和
ll mx[4*maxn]; //维护区间最大值
ll node[maxn];
void pushup(int rt){
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    mx[rt] = max(mx[rt<<1],mx[rt<<1|1]);
}
void build(int l,int r,int rt){
    if(l==r){
        sum[rt] = mx[rt] = node[l];
        return ;
    }
    int m = (l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(int L,int R,int l,int r,int rt){
    if(mx[rt]<=2) return ;
    if(l==r){
        sum[rt] = mx[rt] = s[sum[rt]];
        return ;
    }
    int m = (l+r)>>1;
    if(L <= m) update(L,R,l,m,rt<<1);
    if(m < R)  update(L,R,m+1,r,rt<<1|1);
    pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R) return sum[rt];
    int m = (l+r)>>1;
    ll ans = 0;
    if(L <= m)
        ans += query(L,R,l,m,rt<<1);
    if(R > m)
        ans += query(L,R,m+1,r,rt<<1|1);
    return ans;

}
int main(void){
    std::ios::sync_with_stdio(false);
    for(int i = 1; i <= 1e6; i++){         //预处理求因子个数
        for(int j = i; j <= 1e6; j += i){
            s[j]++;
        }
    }
    int n,m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> node[i];
    build(1,n,1);
    int t,a,b;
    for(int i = 1; i <= m; i++){
        cin >> t >> a >> b;
        if(t==1) update(a,b,1,n,1);
        else{
            cout<<query(a,b,1,n,1)<<endl;
        }
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!