HDU5634-Rikka with Phi

来源:互联网 发布:cl.r27.lol index.php 编辑:程序博客网 时间:2024/06/06 18:50

Rikka with Phi

                                                                      Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
                                                                                                  Total Submission(s): 655    Accepted Submission(s): 214


Problem Description
Rikka and Yuta are interested in Phi function (which is known as Euler's totient function).

Yuta gives Rikka an array A[1..n] of positive integers, then Yuta makes m queries.  

There are three types of queries: 

1lr 

Change A[i] into φ(A[i]), for all i[l,r].

2lrx 

Change A[i] into x, for all i[l,r].

3lr 

Sum up A[i], for all i[l,r].

Help Rikka by computing the results of queries of type 3.

 

Input
The first line contains a number T(T100) ——The number of the testcases. And there are no more than 2 testcases with n>105

For each testcase, the first line contains two numbers n,m(n3×105,m3×105)

The second line contains n numbers A[i]

Each of the next m lines contains the description of the query. 

It is guaranteed that 1A[i]107 At any moment.
 

Output
For each query of type 3, print one number which represents the answer.
 

Sample Input
110 1056 90 33 70 91 69 41 22 77 451 3 91 1 103 3 82 5 6 741 1 83 1 91 2 101 4 92 8 8 693 3 9
 

Sample Output
8012286
 

Source
BestCoder Round #73 (div.1) 
 

Recommend
hujie
 


题意:有3种区间操作:

1.是把区间内的所有数变成它的欧拉函数值

2.是把区间所有数都变成一个数x

3.是查询区间和

解题思路:线段树,维护区间内的数是否相同,区间更新即可


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <map>#include <cmath>#include <set>#include <stack>#include <queue>#include <vector>#include <bitset>#include <functional>using namespace std;#define LL long longconst int INF = 0x3f3f3f3f;int x[10000009], n, m;LL sum[300009 << 2], lazy[300009 << 2];void init(){x[1] = 1;for (int i = 2; i < 10000009; i++) x[i] = i;for (int i = 2; i < 10000009; i++)if (x[i] == i)for (int j = i; j < 10000009; j += i) x[j] = x[j] / i*(i - 1);}void Push(int k, int l,int r){lazy[k << 1] = lazy[k << 1 | 1] = lazy[k];int mid = (l + r) >> 1;sum[k << 1] = (LL)lazy[k] * (mid - l + 1);sum[k << 1 | 1] = (LL)lazy[k] * (r - mid);lazy[k] = -1;}void Merge(int k){sum[k] = sum[k << 1] + sum[k << 1 | 1];lazy[k] = ((lazy[k << 1] == lazy[k << 1 | 1]) ? lazy[k << 1] : -1);}void build(int k, int l, int r){if (l == r) { scanf("%d", &lazy[k]); sum[k] = lazy[k]; return; }int mid = l + r >> 1;build(k << 1, l, mid);build(k << 1 | 1, mid + 1, r);Merge(k);}void update(int k, int l, int r, int ll, int rr, int val,int type){if (ll <= l&&r <= rr&&!type) { lazy[k] = val; sum[k] = (LL)(r - l + 1)*val; return; }if (ll <= l&&r <= rr&&type&&lazy[k] != -1) { lazy[k] = x[lazy[k]]; sum[k] = (LL)lazy[k] * (r - l + 1); return; }int mid = l + r >> 1;if (lazy[k]!=-1) Push(k, l, r);if (ll <= mid) update(k << 1, l, mid, ll, rr, val,type);if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr, val,type);Merge(k);}LL getans(int k, int l, int r, int ll, int rr){if (ll <= l&&r <= rr) return sum[k];int mid = l + r >> 1;LL ans = 0;if (lazy[k]!=-1) Push(k, l, r);if (ll <= mid) ans += getans(k << 1, l, mid, ll, rr);if (rr > mid) ans += getans(k << 1 | 1, mid + 1, r, ll, rr);return ans;}int main(){init();int t;scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);build(1, 1, n);while (m--){int p, l, r, c;scanf("%d%d%d", &p, &l, &r);if (p == 1) update(1, 1, n, l, r,1,1);if (p == 2) scanf("%d", &c), update(1, 1, n, l, r, c,0);if (p == 3) printf("%lld\n", getans(1, 1, n, l, r));}}return 0;}

原创粉丝点击