题意:给你n个数,进行m次操作,分别是将区间[l,r]内的所有数替换成自己的因子数 和 对区间[l,r]进行求和。
题解:可以发现2的因子个数还是2,1的因子个数还是1,所以如果某个数被更新成1或者2之后就不需要再进行更新了。
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define lson l,m,rt<<1 4 #define rson m+1,r,rt<<1|1 5 using namespace std; 6 const int N = 3e5+5; 7 const int M = 1e6+5; 8 ll tree[N<<2]; 9 bool ok[N<<2]; 10 int num[M], a[N]; 11 int n, m; 12 void PushUp(int rt) 13 { 14 tree[rt] = tree[rt<<1] + tree[rt<<1|1]; 15 ok[rt] = ok[rt<<1] && ok[rt<<1|1]; 16 } 17 void Build(int l, int r, int rt) 18 { 19 if(l == r) 20 { 21 tree[rt] = a[l]; 22 if(tree[rt] == 1 || tree[rt] == 2) ok[rt] = 1; 23 else ok[rt] = 0; 24 return ; 25 } 26 int m = l+r >> 1; 27 Build(lson); 28 Build(rson); 29 PushUp(rt); 30 } 31 ll Query(int L, int R, int l, int r, int rt) 32 { 33 if(L <= l && r <= R) 34 return tree[rt]; 35 int m = l+r >> 1; 36 ll ans = 0; 37 if(L <= m) ans += Query(L,R,lson); 38 if(m < R) ans += Query(L,R,rson); 39 return ans; 40 } 41 42 void Revise(int L, int R, int l, int r, int rt) 43 { 44 if(ok[rt]) return ; 45 if(l == r) 46 { 47 tree[rt] = num[tree[rt]]; 48 if(tree[rt] == 1 || tree[rt] == 2) ok[rt] = 1; 49 return ; 50 } 51 int m = l+r >> 1; 52 if(L <= m) Revise(L,R,lson); 53 if(m < R) Revise(L,R,rson); 54 PushUp(rt); 55 } 56 int main() 57 { 58 ios::sync_with_stdio(false); 59 cin.tie(0); 60 cout.tie(0); 61 memset(num, 0, sizeof(num)); 62 for(int i = 1; i < M; i++) 63 for(int j = i; j < M; j+=i) 64 num[j]++; 65 cin >> n >> m; 66 for(int i = 1; i <= n; i++) 67 cin >> a[i]; 68 Build(1,n,1); 69 int q, l, r; 70 while(m--) 71 { 72 cin >> q >> l >> r; 73 if(q == 2) 74 cout << Query(l,r,1,n,1) << endl; 75 else 76 Revise(l,r,1,n,1); 77 } 78 return 0; 79 }
原文地址:https://www.cnblogs.com/MingSD/p/8412621.html
时间: 2024-10-29 18:01:00