F. SUM and REPLACE
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Let D(x) be the number of positive divisors of a positive integer x. For example, D(2) = 2 (2 is divisible by 1 and 2), D(6) = 4 (6 is divisible by 1, 2, 3 and 6).
You are given an array a of n integers. You have to process two types of queries:
REPLACE l r — for every replace ai with D(ai);
SUM l r — calculate .
Print the answer for each SUM query.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 3·105) — the number of elements in the array and the number of queries to process, respectively.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106) — the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th query. If ti = 1, then i-th query is REPLACE li ri, otherwise it's SUM li ri (1 ≤ ti ≤ 2, 1 ≤ li ≤ ri ≤ n).
There is at least one SUM query.
Output
For each SUM query print the answer to it.
Example
inputCopy
7 6
6 4 1 10 3 2 4
2 1 7
2 4 5
1 3 5
2 4 4
1 5 7
2 1 7
outputCopy
30
13
4
22
/contest/920/problem/F
题意:
给你一个含有n个数的数组,和m个操作
操作1:将l~r中每一个数\(a[i]\)变成 \(d(a[i])\)
其中$ d(x)$ 是约数个数函数。
操作2: 求l~r的a[i] 的sum和。
思路:
$ d(x)$ 约数个数函数可以利用线性筛预处理处理。
又因为 \(d(2)=2\) 和 \(d(1)=1\) 操作1对a[i]等于1或者2没有影响。
那么我们可以对一个区间中全都是1或者2不更新操作。
同时 \(d(x)\) 是收敛函数, 在1e6 的范围内,最多不超过5次改变就会收敛到1或2.
所以更新操作可以暴力解决,
同时用线段树维护即可。
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>#include <vector>#include <iomanip>#define ALL(x) (x).begin(), (x).end()#define sz(a) int(a.size())#define rep(i,x,n) for(int i=x;i<n;i++)#define repd(i,x,n) for(int i=x;i<=n;i++)#define pii pair<int,int>#define pll pair<long long ,long long>#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define MS0(X) memset((X), 0, sizeof((X)))#define MSC0(X) memset((X), '\0', sizeof((X)))#define pb push_back#define mp make_pair#define fi first#define se second#define eps 1e-6#define gg(x) getInt(&x)#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))#define du2(a,b) scanf("%d %d",&(a),&(b))#define du1(a) scanf("%d",&(a));using namespace std;typedef long long ll;ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}inline void getInt(int *p);const int maxn = 1000010;const int inf = 0x3f3f3f3f;/*** TEMPLATE CODE * * STARTS HERE ***/// d(n)表示n的约数个数和// prime[i]表示第i个质数//num[i]表示i的最小质因子出现次数int sshu[maxn];int N = maxn;int num[maxn];int d[maxn];bool no[maxn];int tot;void prepare(){d[1] = 1; num[1] = 1;for (int i = 2; i < N; i++) {if (!no[i]) {sshu[++tot] = i;d[i] = 2; num[i] = 1;}for (int j = 1; j <= tot && sshu[j]*i < N; j++) {int v = sshu[j] * i;no[v] = 1;if (i % sshu[j] == 0) {num[v] = num[i] + 1;d[v] = d[i] / num[v] * (num[v] + 1);break;}d[v] = d[i] << 1; num[v] = 1;}}//for (int i=1;i<=10;i++) printf("%d\n",d[i]);}int a[maxn];struct node {int l, r;int laze;bool isall;ll num;} segment_tree[maxn << 2];void pushup(int rt){segment_tree[rt].num = segment_tree[rt << 1].num + segment_tree[rt << 1 | 1].num;segment_tree[rt].isall = segment_tree[rt << 1].isall & segment_tree[rt << 1 | 1].isall;}void build(int rt, int l, int r){segment_tree[rt].l = l;segment_tree[rt].r = r;if (l == r) {segment_tree[rt].num =a[l];if (segment_tree[rt].num == 1 || segment_tree[rt].num == 2) {segment_tree[rt].isall = 1;}return ;}int mid = (l + r) >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushup(rt);}void update(int rt, int l, int r){if (l <= segment_tree[rt].l && r >= segment_tree[rt].r && segment_tree[rt].isall) {return;}if (segment_tree[rt].l == segment_tree[rt].r) {segment_tree[rt].num = d[segment_tree[rt].num];if (segment_tree[rt].num == 1 || segment_tree[rt].num == 2) {segment_tree[rt].isall = 1;}return ;} else {int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;if (mid >= l) {update(rt << 1, l, r);}if (mid < r) {update(rt << 1 | 1, l, r);}pushup(rt);}}ll query(int rt, int l, int r){if (segment_tree[rt].l >= l && segment_tree[rt].r <= r) {ll res = 0ll;res += segment_tree[rt].num;return res;}int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;ll res = 0ll;if (mid >= l) {res += query(rt << 1, l, r);}if (mid < r) {res += query(rt << 1 | 1, l, r);}return res;}int main(){//freopen("D:\\code\\text\\input.txt","r",stdin);//freopen("D:\\code\\text\\output.txt","w",stdout);prepare();int n, m;du2(n, m);repd(i, 1, n) {du1(a[i]);}build(1, 1, n);repd(i, 1, m) {int op; int l, r;du3(op, l, r);if (op == 1) {update(1, l, r);} else {printf("%lld\n", query(1, l, r));}}return 0;}inline void getInt(int *p){char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}} else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}}}