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;
}
posted @ 2016-02-22 13:23  qscqesze  阅读(412)  评论(0编辑  收藏  举报