hdu5634 Rikka with Phi(线段树+欧拉函数)

添加链接描述
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(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

Source
BestCoder Round #73 (div.1)
思路:对于操作1最多进行log次变换就可以把它变为1,所以对于多个连续的1我们可以把它合并到一起。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+1;
const int N=1e7+1;
ll euler[N];
struct node{
    int l,r;
    ll lazy,w;
}tree[maxn<<2];
void get_euler(){ //欧拉函数 
   memset(euler, 0, sizeof(euler));
    euler[1] = 1;
    for(ll i = 2; i < N; i++) if(!euler[i])
        for(ll j = i; j < N; j += i){
            if(!euler[j]) euler[j] = j;
            euler[j] = euler[j] / i * (i-1);
        }
}
void pushup(int x)
{
    tree[x].w=tree[x<<1].w+tree[x<<1|1].w;;
    tree[x].lazy=(tree[x<<1].lazy==tree[x<<1|1].lazy)?tree[x<<1].lazy:0;
}
void pushdown(int x)
{
    if(tree[x].lazy)
    {
        tree[x<<1].lazy=tree[x<<1|1].lazy=tree[x].lazy;
        tree[x<<1].w=tree[x].lazy*(tree[x<<1].r-tree[x<<1].l+1);
        tree[x<<1|1].w=tree[x].lazy*(tree[x<<1|1].r-tree[x<<1|1].l+1);
        tree[x].lazy=0; 
    }
}
void build(int x,int l,int r)
{
    tree[x].l=l;tree[x].r=r;
    if(l==r)
    {
        scanf("%lld",&tree[x].w);
        tree[x].lazy=tree[x].w;
        return ;
    }
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    pushup(x);
}
void update1(int x,int l,int r)
{
    if(tree[x].lazy&&l<=tree[x].l&&tree[x].r<=r)
    {
        tree[x].w=euler[tree[x].lazy]*(tree[x].r-tree[x].l+1);
        tree[x].lazy=euler[tree[x].lazy];
        return ;
    }
    pushdown(x);
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid) update1(x<<1,l,r);
    else if(l>mid) update1(x<<1|1,l,r);
    else update1(x<<1,l,mid),update1(x<<1|1,mid+1,r);
    pushup(x);
}
void update2(int x,int l,int r,ll v)
{
    if(l<=tree[x].l&&tree[x].r<=r)
    {
        tree[x].w=v*(tree[x].r-tree[x].l+1);
        tree[x].lazy=v;
        return ;
    }
    pushdown(x);
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid) update2(x<<1,l,r,v);
    else if(l>mid) update2(x<<1|1,l,r,v);
    else update2(x<<1,l,mid,v),update2(x<<1|1,mid+1,r,v);
    pushup(x);
}
ll query(int x,int l,int r)
{
    if(l<=tree[x].l&&tree[x].r<=r) return tree[x].w;
    pushdown(x); 
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid) return query(x<<1,l,r);
    else if(l>mid) return query(x<<1|1,l,r);
    else return query(x<<1,l,mid)+query(x<<1|1,mid+1,r); 
}
int main()
{
    int T,n,m,op,l,r;
    get_euler();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--)
        {
            ll v;
            scanf("%d%d%d",&op,&l,&r);
            if(op==1) update1(1,l,r);
            else if(op==2) scanf("%lld",&v),update2(1,l,r,v);
            else printf("%lld\n",query(1,l,r));
         } 
    }
}
发布了283 篇原创文章 · 获赞 0 · 访问量 7316

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105018227
今日推荐