[codeforces920F]SUM and REPLACE

该博客介绍了如何解决一道编程竞赛题目,涉及对数组进行两种类型的操作:一种是将指定区间内的元素替换为其因数个数(D(x)),另一种是计算指定区间的元素和。题目给出了输入输出示例,并指出由于元素范围较小,可以预先计算所有数的因数个数。解决方案提到了使用线段树进行高效处理,强调了修改操作的暴力实现策略。
摘要由CSDN通过智能技术生成

time limit per test : 2 seconds
memory limit per test : 256 megabytes

分数:2000

Let D ( x ) D(x) D(x) be the number of positive divisors of a positive integer x x x. For example, D ( 2 )   =   2 D(2) = 2 D(2)=2 ( 2 2 2 is divisible by 1 1 1 and 2 2 2), D ( 6 )   =   4 D(6) = 4 D(6)=4 ( 6 6 6 is divisible by 1 , 2 , 3 1, 2, 3 1,2,3 and 6 6 6).
You are given an array a of n integers. You have to process two types of queries:

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

Print the answer for each SUM query.

Input

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

The second line contains n integers a 1 , a 2 , . . . , a n ( 1   ≤   a i   ≤   1 0 6 ) a_1, a_2, ..., a_n (1 ≤ a_i ≤ 10^6) a1,a2,...,an(1ai106) — the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th query. If ti = 1, then i-th query is R E P L A C E REPLACE REPLACE l i l_i li r i r_i ri, otherwise it’s S U M SUM SUM l i l_i li r i ( 1   ≤   t i   ≤   2 , 1   ≤   l i   ≤   r i   ≤   n ) r_i (1 ≤ t_i ≤ 2, 1 ≤ l_i ≤ r_i ≤ n) ri(1ti2,1lirin).
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

题意:
给定一个序列
需要支持两种操作,
第一种操作是将区间i=L~R所有a[i]变为D(a[i]) (D(x)为x的因数个数)
第二种操作是求区间i=L~R所a[i]的和

题解:
线段树经典题
每个点会被改动的次数很少
所以修改的时候只需要暴力修改即可
因为a[i]的最大值只有100w所以可以预处理出所有的D(x)

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int D[1000004];
void pre(){
    memset(D,0,sizeof(D));
    for(int i=1;i<=1000000;i++){
        for(int j=i;j<=1000000;j+=i){
            D[j]++;
        }
    }
}
int n,m;
int a[300004];
struct seg{
    int l,r;
    ll w;
    bool tag;
}tr[1200004];
void build(int k,int l,int r){
    tr[k].l=l;tr[k].r=r;tr[k].tag=0;
    if(l==r){
        tr[k].w=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}
void modify(int k,int a,int b){
    int l=tr[k].l,r=tr[k].r;
    if(tr[k].tag)return ;
    if(l==r){
        tr[k].w=D[tr[k].w];
        if(tr[k].w==D[tr[k].w])tr[k].tag=1;
        return ;
    }
    int mid=(l+r)>>1;
    if(b<=mid)modify(k<<1,a,b);
    else if(a>mid)modify(k<<1|1,a,b);
    else{
        modify(k<<1,a,mid);
        modify(k<<1|1,mid+1,b);
    }
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
    tr[k].tag=(tr[k<<1].tag&&tr[k<<1|1].tag);
}
ll query(int k,int a,int b){
    int l=tr[k].l,r=tr[k].r;
    if(l==a&&r==b)return tr[k].w;
    int mid=(l+r)>>1;
    if(b<=mid)return query(k<<1,a,b);
    else if(a>mid)return query(k<<1|1,a,b);
    else {
        return query(k<<1,a,mid)+query(k<<1|1,mid+1,b);
    }
}
int main(){
    pre();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    build(1,1,n);
    while(m--){
        int t,l,r;
        scanf("%d%d%d",&t,&l,&r);
        if(t==1){
            modify(1,l,r);
        }
        if(t==2){
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值