HDU 5634 Rikka with Phi 线段树
Rikka with Phi
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=5634
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(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.
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
Hint
题意
给出一个长度为n的数组A,接下来有m次操作。
1 l r
对所有区间[l,r]中的整数i,把A_i变成φ(A[i])(指欧拉函数)
2 l r x
对所有区间[l,r]中的整数i,把A[i]变成x
3 l r
询问[l,r]的区间和。
题解:
线段树直接暴力就好了
对于更新1,我们会发现在不超过20次的情况下,这个点的值就会变成1
于是我们就把变成1的值的位置强行和周围合并一下就好了
然后在更新的时候,发现到合并在一起了的,就不往下走了
否则就直接暴力往下走
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+7;
const int N = 1e7+7;
long long phi[N],n;
long long a[maxn];
void phi1()
{
memset(phi,0,sizeof(phi));
phi[1]=1;
for(long long i=2;i<N;i++)
{
if(!phi[i])
{
for(long long j=i;j<N;j+=i)
{
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
typedef long long SgTreeDataType;
struct treenode
{
int L , R ;
SgTreeDataType sum , lazy;
void update(SgTreeDataType v)
{
sum = (R-L+1)*v;
lazy = v;
}
};
treenode tree[maxn*4];
inline void push_down(int o)
{
SgTreeDataType lazyval = tree[o].lazy;
if(lazyval)tree[2*o].update(lazyval) , tree[2*o+1].update(lazyval);
}
inline void push_up(int o)
{
tree[o].sum = tree[2*o].sum + tree[2*o+1].sum;
if(tree[o*2+1].lazy == tree[o*2].lazy)tree[o].lazy = tree[o*2].lazy;
else tree[o].lazy = 0;
}
inline void build_tree(int L , int R , int o)
{
tree[o].L = L , tree[o].R = R;
if(L==R)
tree[o].sum = tree[o].lazy = a[L];
if (R > L)
{
int mid = (L+R) >> 1;
build_tree(L,mid,o*2);
build_tree(mid+1,R,o*2+1);
push_up(o);
}
}
inline void update1(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if (tree[o].lazy && QL <= L && R <= QR)
{
tree[o].update(phi[tree[o].lazy]);
}
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) update1(QL,QR,o*2);
if (QR > mid) update1(QL,QR,o*2+1);
push_up(o);
}
}
inline void update2(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) tree[o].update(v);
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) update2(QL,QR,v,o*2);
if (QR > mid) update2(QL,QR,v,o*2+1);
push_up(o);
}
}
inline SgTreeDataType query(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) return tree[o].sum;
else
{
push_down(o);
int mid = (L+R)>>1;
SgTreeDataType res = 0;
if (QL <= mid) res += query(QL,QR,2*o);
if (QR > mid) res += query(QL,QR,2*o+1);
push_up(o);
return res;
}
}
int main()
{
phi1();
int t;scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build_tree(1,n,1);
while(m--)
{
int op,x,y,z;
scanf("%d%d%d",&op,&x,&y);
if(op==1)update1(x,y,1);
if(op==2)scanf("%d",&z),update2(x,y,z,1);
if(op==3)printf("%lld\n",query(x,y,1));
}
}
return 0;
}