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; }
来源:https://www.cnblogs.com/AC-AC/p/12461852.html