Rikka with Phi
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 207 Accepted Submission(s): 64
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.
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(T≤100)
——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(n≤3×105,m≤3×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 1≤A[i]≤107 At any moment.
For each testcase, the first line contains two numbers n,m(n≤3×105,m≤3×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 1≤A[i]≤107 At any moment.
Output
For each query of type 3, print one number which represents the answer.
Sample Input
1 10 10 56 90 33 70 91 69 41 22 77 45 1 3 9 1 1 10 3 3 8 2 5 6 74 1 1 8 3 1 9 1 2 10 1 4 9 2 8 8 69 3 3 9
Sample Output
80 122 86
题意:给你n个数和m次操作。
1 x y 表示将区间[x, y]里面的数变为自己的欧拉函数。
2 x y v 表示将区间[x, y]里面的数修改为v。
3 x y 表示求区间[x, y]的和。
思路:n<=10^7的数,最多进行logn次欧拉函数求解就会变成1。
对于操作2,可以直接区间更新。
对于操作1,我们标记 每个区间是否满足直接区间更新的条件——条件为左、右子区间的所有数全部相等。若某一个区间满足条件,可以用一个变量记录当前区间的元素值。这样在更新时,没必要直接更新到底。初始显然只有叶子区间,之后每次两个子区间改变,我们都需要将信息向上传递。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
const int MAXN = 3*1e5+1;
const int MAXM = 1e7+1;
LL euler[MAXM];
void Geteuler()
{
memset(euler, 0, sizeof(euler));
euler[1] = 1;
for(LL i = 2; i < MAXM; i++) if(!euler[i])
for(LL j = i; j < MAXM; j += i){
if(!euler[j]) euler[j] = j;
euler[j] = euler[j] / i * (i-1);
}
}
struct Tree{
int l, r, len; LL sum, lazy;
};
Tree tree[MAXN<<2];
void PushUp(int o){
tree[o].sum = tree[ll].sum + tree[rr].sum;
if(tree[ll].lazy == tree[rr].lazy) tree[o].lazy = tree[ll].lazy;
else tree[o].lazy = 0;
}
void PushDown(int o)
{
if(tree[o].lazy)
{
tree[ll].lazy = tree[rr].lazy = tree[o].lazy;
tree[ll].sum = tree[o].lazy * tree[ll].len;
tree[rr].sum = tree[o].lazy * tree[rr].len;
}
}
void Build(int o, int l, int r)
{
tree[o].l = l; tree[o].r = r;
tree[o].len = r - l + 1;
if(l == r)
{
scanf("%lld", &tree[o].sum);
tree[o].lazy = tree[o].sum;
return ;
}
int mid = (l + r) >> 1;
Build(ll, l, mid); Build(rr, mid+1, r);
PushUp(o);
}
void Update1(int o, int L, int R)
{
if(tree[o].lazy && L == tree[o].l && R == tree[o].r)
{
tree[o].sum = euler[tree[o].lazy] * tree[o].len;
tree[o].lazy = euler[tree[o].lazy];
return ;
}
PushDown(o);
int mid = (tree[o].l + tree[o].r) >> 1;
if(R <= mid) Update1(ll, L, R);
else if(L > mid) Update1(rr, L, R);
else { Update1(ll, L, mid); Update1(rr, mid+1, R); }
PushUp(o);
}
void Update2(int o, int L, int R, int v)
{
if(L == tree[o].l && R == tree[o].r)
{
tree[o].lazy = v;
tree[o].sum = 1LL * v * tree[o].len;
return ;
}
PushDown(o);
int mid = (tree[o].l + tree[o].r) >> 1;
if(R <= mid) Update2(ll, L, R, v);
else if(L > mid) Update2(rr, L, R, v);
else { Update2(ll, L, mid, v); Update2(rr, mid+1, R, v); }
PushUp(o);
}
LL Query(int o, int L, int R)
{
if(L == tree[o].l && R == tree[o].r)
return tree[o].sum;
PushDown(o);
int mid = (tree[o].l + tree[o].r) >> 1;
if(R <= mid) return Query(ll, L, R);
else if(L > mid) return Query(rr, L, R);
else return Query(ll, L, mid) + Query(rr, mid+1, R);
}
int main()
{
Geteuler();
int t; scanf("%d", &t);
while(t--)
{
int n, m;
scanf("%d%d", &n, &m);
Build(1, 1, n);
while(m--)
{
int op, x, y, v;
scanf("%d%d%d", &op, &x, &y);
if(op == 1) Update1(1, x, y);
else if(op == 2) {scanf("%d", &v); Update2(1, x, y, v);}
else if(op == 3) printf("%lld\n", Query(1, x, y));
}
}
return 0;
}