• 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
    ",query(x,y,1));
            }
        }
      return 0;
    }
  • 相关阅读:
    hdu 5400 Arithmetic Sequence
    【小超_Android】android上开源的酷炫的交互动画和视觉效果:Interactive-animation
    项目PMO工作
    HDU 3340 Rain in ACStar(线段树+几何)
    再看数据库——(6)连接
    Android 安装应用后点击打开带来的问题
    Notes 和 Domino 已知限制
    去哪网实习总结:JavaWeb配置404页面(JavaWeb)
    Android 怎样实现 焦点图的 无线循环滑动的状态?
    【JNI探索之路系列】之七:JNI要点总结
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5206843.html
Copyright © 2020-2023  润新知