码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 920 F SUM and REPLACE

时间:2018-02-03 23:07:01      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:proc   i++   lower   break   update   std   follow   复杂度   using   

#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;
}

  

题目描述

 

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

 

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

 

REPLACE l l r r — for every replace a_{i} a 

i

? with D(a_{i}) D(a 

i

? ) ;

SUM l l r r — calculate .

Print the answer for each SUM query.

 

输入输出格式

 

输入格式:

The first line contains two integers n n and m m ( 1<=n,m<=3·10^{5} 1<=n,m<=3?10 

5

  ) — the number of elements in the array and the number of queries to process, respectively.

 

The second line contains n n integers a_{1} a 

1

? , a_{2} a 

2

? , ..., a_{n} a 

n

? ( 1<=a_{i}<=10^{6} 1<=a 

i

? <=10 

6

  ) — the elements of the array.

 

Then m m lines follow, each containing 3 3 integers t_{i} t 

i

? , l_{i} l 

i

? , r_{i} r 

i

? denoting i i -th query. If t_{i}=1 t 

i

? =1 , then i i -th query is REPLACE l_{i} l 

i

? r_{i} r 

i

? , otherwise it‘s SUM l_{i} l 

i

? r_{i} r 

i

? ( 1<=t_{i}<=2 1<=t 

i

? <=2 , 1<=l_{i}<=r_{i}<=n 1<=l 

i

? <=r 

i

? <=n ).

 

There is at least one SUM query.

 

输出格式:

For each SUM query print the answer to it.

 

输入输出样例

 

输入样例#1: 

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

输出样例#1: 

30

13

4

22

 

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

 

Codeforces 920 F SUM and REPLACE

标签:proc   i++   lower   break   update   std   follow   复杂度   using   

原文地址:https://www.cnblogs.com/JYYHH/p/8410775.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!