Codeforces 920 F SUM and REPLACE

    Dicription

Let D(x) be the number of positive divisors of a positive integer x. For example, D(2) = 2 (2 is divisible by 1 and 2), D(6) = 4 (6 is divisible by 1, 2, 3 and 6).

You are given an array a of n integers. You have to process two types of queries:

  1. REPLACE l r — for every  replace ai with D(ai);
  2. SUM l r — calculate .

Print the answer for each SUM query.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 3·105) — the number of elements in the array and the number of queries to process, respectively.

The second line contains n integers a1a2, ..., an (1 ≤ ai ≤ 106) — the elements of the array.

Then m lines follow, each containing 3 integers tiliri denoting i-th query. If ti = 1, then i-th query is REPLACE li ri, otherwise it's SUM li ri (1 ≤ ti ≤ 2, 1 ≤ li ≤ ri ≤ n).

There is at least one SUM query.

Output

For each SUM query print the answer to it.

Example
Input
7 6
6 4 1 10 3 2 4
2 1 7
2 4 5
1 3 5
2 4 4
1 5 7
2 1 7
Output
30
13
4
22

可以发现每个数被改若干次之后就会变成2(或者这个数本来就为1它也只能是1),而这个次数的最大值也不会很大,所以我们就可以维护一个还没有变成≤2的位置集合,然后暴力单点修改。又因为是求前缀和,所以我们再维护一个树状数组就好了,时间复杂度O(N*log²N)

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define ll long long
#define maxn 300005
#define maxm 1000000
using namespace std;
set<int> s;
set<int> ::iterator it;
int zs[maxn],t=0,low[maxm+5];
int d[maxm+5],n,m,le,ri,opt;
bool v[maxm+5];
int a[maxn];
ll f[maxn],qz[maxn];

inline void init(){
    d[1]=1,low[1]=1;
    for(int i=2;i<=maxm;i++){
        if(!v[i]) zs[++t]=i,d[i]=2,low[i]=i;
        for(int j=1,u;j<=t&&(u=zs[j]*i)<=maxm;j++){
            v[u]=1;
            if(!(i%zs[j])){
                low[u]=low[i]*zs[j];
                if(low[i]==i) d[u]=d[i]+1;
                else d[u]=d[low[u]]*d[i/low[i]];
                break;
            }
            low[u]=zs[j],d[u]=d[i]<<1;
        }
    }
    
}

inline void update(int x,int y){
    for(;x<=n;x+=x&-x) f[x]+=(ll)y;
}

inline ll query(ll x){
    ll an=0;
    for(;x;x-=x&-x) an+=f[x];
    return an;
}

inline void solve(){
    int pre=*s.lower_bound(le);
    while(pre<=ri){
        update(pre,d[a[pre]]-a[pre]);
        a[pre]=d[a[pre]];
        if(a[pre]<=2) s.erase(pre);
        pre=*s.upper_bound(pre);
    }
}

int main(){
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",a+i);
        qz[i]=qz[i-1]+(ll)a[i];
        s.insert(i);
    }
    s.insert(n+1);
    
    while(m--){
        scanf("%d%d%d",&opt,&le,&ri);
        if(opt==2) printf("%lld\n",qz[ri]-qz[le-1]+query(ri)-query(le-1));
        else solve();
    }
    
    return 0;
}

  

posted @ 2018-02-03 21:16  蒟蒻JHY  阅读(310)  评论(0编辑  收藏  举报