Rikka with Phi

Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

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:

1 l r

Change A[i] into φ(A[i]), for all i∈[l,r].

2 l r x

Change A[i] into x, for all i∈[l,r].

3 l r

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)

Recommend

hujie | We have carefully selected several similar problems for you: 6297 6296 6295 6294 6293

这又是一道与众不同的线段树,操作是区间覆盖,区间取欧拉函数,区间求和。

看起来这操作挺吓人的。但在我们AC了另外一道黑科技线段树与或之后,这题其实也不算什么了。

我们知道,一个数在不断变成它的欧拉函数若干次之后恒为一,且许多数的欧拉函数值都是相同的(数据随机)。这样的话,如果我们将修改操作进行改进,只有在当前区间在询问区间以内且当前区间中的数都相同时,我们才对这个区间进行修改,否则我们继续对其的左右儿子进行修改,尽管看起来这种思路效率极低,但如果我们仔细分析会发现,一个区间中的数被1,2" role="presentation" style="position: relative;">1,21,2操作修改若干次以后,都会变成相同的,因此这个算法的效率就有了保障,平摊下来差不多就O(nlogn)" role="presentation" style="position: relative;">O(nlogn)O(nlogn)的时间复杂度。因此问题不大。

代码如下:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 300005
using namespace std;
inline long long read(){
    long long ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    return ans;
}
long long phi[10000005];
bool pr[10000005];
long long prime[1000005];
int t,n,m,a[N],tot=0;
struct Node{int l,r;long long sum,num;}T[N<<2];
inline void init(){
    phi[1]=1;
    for(int i=2;i<=10000000;++i){
        if(!pr[i])prime[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot;++j){
            if(i*prime[j]>10000000)break;
            pr[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}
inline void pushup(int p){
    T[p].sum=T[lc].sum+T[rc].sum;
    T[p].num=T[lc].num==T[rc].num?T[lc].num:0;
}
inline void pushnow(int p,long long v){
    T[p].num=v;
    T[p].sum=v*(T[p].r-T[p].l+1);
}
inline void pushdown(int p){
    if(!T[p].num)return;
    pushnow(lc,T[p].num);
    pushnow(rc,T[p].num);
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r;
    if(l==r){
        T[p].num=T[p].sum=a[l];
        return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    pushup(p);
}
inline void modify(int p,int ql,int qr){
    if(qr<T[p].l||T[p].r<ql)return;
    if(ql<=T[p].l&&T[p].r<=qr&&T[p].num){
        pushnow(p,phi[T[p].num]);
        return;
    }
    pushdown(p);
    if(qr<=mid)modify(lc,ql,qr);
    else if(ql>mid)modify(rc,ql,qr);
    else modify(lc,ql,mid),modify(rc,mid+1,qr);
    pushup(p);
}
inline void update(int p,int ql,int qr,long long v){
    if(qr<T[p].l||T[p].r<ql)return;
    if(ql<=T[p].l&&T[p].r<=qr){
        pushnow(p,v);
        return;
    }
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline long long query(int p,int ql,int qr){
    if(qr<T[p].l||T[p].r<ql)return 0;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].sum;
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return query(lc,ql,mid)+query(rc,mid+1,qr);
}
int main(){
    init();
    t=read();
    while(t--){
        memset(T,0,sizeof(T));
        n=read(),m=read();
        for(int i=1;i<=n;++i)a[i]=read();
        build(1,1,n);
        while(m--){
            int op=read(),l=read(),r=read();
            if(op==1)modify(1,l,r);
            if(op==2){
                long long v=read();
                update(1,l,r,v);
            }
            if(op==3)printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}

2018.07.03 HDU Rikka with Phi(线段树)的更多相关文章

  1. HDU5634 Rikka with Phi 线段树

    // HDU5634 Rikka with Phi 线段树 // 思路:操作1的时候,判断一下当前区间是不是每个数都相等,在每个数相等的区间上操作.相当于lazy,不必更新到底. #include & ...

  2. HDU 5634 Rikka with Phi 线段树

    题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...

  3. Rikka with Phi 线段树

    Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds ...

  4. 2018.07.08 hdu6183 Color it(线段树)

    Color it Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Proble ...

  5. 2018.07.08 POJ 2481 Cows(线段树)

    Cows Time Limit: 3000MS Memory Limit: 65536K Description Farmer John's cows have discovered that the ...

  6. 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

  7. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  8. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  9. 2018.07.23 hdu5828 Rikka with Sequence(线段树)

    传送门 这道题维护区间加,区间开根,区间求和. 线段树常规操作. 首先回忆两道简单得多的线段树. 第一个:区间覆盖,区间加,区间求和. 第二个:区间开根,区间求和. 这两个是名副其实的常规操作. 但这 ...

随机推荐

  1. 机器学习入门-使用GridSearch进行网格参数搜索GridSeach(RandomRegressor(), param_grid, cv=3)

    1.GridSeach(RandomRegressor(), param_grid, cv=3) GridSearch第一个参数是算法本身, 第二个参数是传入的参数组合, cv表示的是交叉验证的次数 ...

  2. cmd 查看本地端口被占用程序

    netstat -ano 列出当前活动的网络连接 参数:-a所有侦听端口  -n以数字格式显示地址和端口号 -o显示进程号 tasklist|find "8888" 找出占用888 ...

  3. log4j2搭建记录

    今天新建了一个项目,自己弄的小玩意,想要做的正式点,就想引入日志.就想到了log4j2,经过几个小时的努力,还真的可以用了,下面就记录一下我是怎么做的. 下面是总的结构: 下面是MAVEN依赖: &l ...

  4. java编写一个汽车类,有属性:品牌、型号、排量、速度,有方法:启动、加速、转弯、刹车、息火

    /* * 汽车实体类 * 类里面有属性和方法 */public class Car {    String  brand;   //汽车品牌    String modelNumber; //汽车型号 ...

  5. 给vim编辑器自动添加行号

    1.只改变当前用户的vim 在~目录下  vim .vimrc添加一行 set number 即可(普通用户权限即可) 2. 改变所有用户的vim 打开文件 /etc/vimrc 添加一行 set n ...

  6. xshell分隔符

    1.分隔符设置 \ :;`!@#$%^&()+|[]{}'",<>? 2.左键点击选中,右键点击复制

  7. cdoj第13th校赛初赛H - Hug the princess

    http://acm.uestc.edu.cn/#/contest/show/54 H - Hug the princess Time Limit: 3000/1000MS (Java/Others) ...

  8. GridView控件中的一些常见问题

    1. 无法获取模板列中的值,使用FindControl()方法无效: 给模板列中添加隐藏域,并给隐藏域绑定要获取的值,代码如下: <asp:HiddenField ID="hfIsFr ...

  9. 使用select实现多并发的socket的功能

    select是一个io多路复用的io模型,也叫做事件驱动的io模型,我们今天用select来实现一个多并发的socket的聊天的程序 先看下server端的代码 import socket impor ...

  10. 动态调用WebService方法

      好像很多人做WebService的时候都是直接添加引用的方式,然后调用服务端的方法.这样就个问题,就是每次我服务端添加了方法或者修改了方法后都要更新Web引用,这样比较麻烦.下面给一个不用添加引用 ...