zoukankan      html  css  js  c++  java
  • codeforces CF920F SUM and REPLACE 线段树 线性筛约数

    $ Rightarrow $ 戳我进CF原题

    F. SUM and REPLACE


    time limit per test: 2 seconds
    memory limit per test: 256 megabytes
    input: standard input
    output: standard output

     

    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 quad l quad r $ —— for every $ i in [l,r] $ replace $ a_i $ with $ D(a_i) $ ;
    $ 2. SUM quad l quad r $ —— calculate $ sum_{i=l}^r a_i $ .
     
    Print the answer for each $ SUM $ query.
     

    Input

    The first line contains two integers $ n $ and $ m (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 integers $ a_1, a_2, ..., a_n (1 ≤ ai ≤ 10^6) $ — the elements of the array.
     
    Then $ m $ lines follow, each containing $ 3 $ integers $ t_i, l_i, r_i $ denoting $ i $ -th query.
    If $ ti = 1 $ , then $ i $ -th query is $ REPLACE quad l_i quad r_i $ , otherwise it's $ SUM quad l_i quad r_i (1 ≤ t_i ≤ 2, 1 ≤ l_i ≤ r_i ≤ n) $ .
     
    There is at least one $ SUM $ query.
     

    Output

    For each $ SUM $ query print the answer to it.
     

    Examples

    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
    

     

    题目大意

    • 给你 $ n $ 个数,进行 $ m $ 次操作,分别是将区间 $ [l,r] $ 内的所有数替换成自己的因子数 和 对区间 $ [l,r] $ 进行求和。

    • 数据范围: $ 1 le n,m le 3 imes 10^5 $
       

    思路

    • 首先可以用线段树来维护序列,每次暴力修改。
      因为 $ D(1)=1, D(2)=2 $,因此当一个区间的最大值小于2时就不需要修改。
       
    • 又因为每次修改只会让值减少,而且每个数最多会被修改 $ O(log_n) $ 次,因此能够保证复杂度
       

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXM 1000005
    #define N 300005
    #define int long long
    int n,m,M;
    int d[MAXM],c[MAXM],p[MAXM];
    bool vis[MAXM];
    void pre(){
        d[1]=1;
        for(int i=2;i<=M;++i){
            if(!vis[i]){ p[++p[0]]=i; vis[i]=1; d[i]=2; c[i]=1; }
            for(int j=1;j<=p[0]&&1ll*i*p[j]<=M;++j){
                vis[i*p[j]]=1;
                if(i%p[j]==0){
                    d[i*p[j]]=d[i]/(c[i]+1)*(c[i]+2);
                    c[i*p[j]]=c[i]+1;
                    break;
                }
                d[i*p[j]]=d[i]*2;
                c[i*p[j]]=1;
            }
        }
    }
    int sum[N<<2];
    bool flag[N<<2];
    void build(int o,int l,int r){
        if(l==r){
            scanf("%lld",&sum[o]);
            if(sum[o]==1||sum[o]==2) flag[o]=1;
            M=max(M,sum[o]);
            return;
        }
        int mid=l+r>>1;
        build(o<<1,l,mid); build(o<<1|1,mid+1,r);
        sum[o]=sum[o<<1]+sum[o<<1|1];
        flag[o]=flag[o<<1]&flag[o<<1|1];
    }
    void updata(int o,int l,int r,int L,int R){
        if(flag[o]) return;
        if(l==r&&L<=l&&l<=R){
            sum[o]=d[sum[o]];
            if(sum[o]==1||sum[o]==2) flag[o]=1;
            return;
        }
        int mid=l+r>>1;
        if(L>mid) updata(o<<1|1,mid+1,r,L,R);
        else if(R<=mid) updata(o<<1,l,mid,L,R);
        else {
            updata(o<<1,l,mid,L,R);
            updata(o<<1|1,mid+1,r,L,R);
        }
        sum[o]=sum[o<<1]+sum[o<<1|1];
        flag[o]=flag[o<<1]&flag[o<<1|1];	
    }
    int query(int o,int l,int r,int L,int R){
        if(L<=l&&r<=R) return sum[o];
        int mid=l+r>>1;
        if(L>mid) return query(o<<1|1,mid+1,r,L,R);
        else if(R<=mid) return query(o<<1,l,mid,L,R);
        else return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
    }
    signed main(){
        scanf("%lld %lld",&n,&m);
        build(1,1,n);
        pre();
        while(m--){
            int opt,x,y;
            scanf("%lld %lld %lld",&opt,&x,&y);
            if(opt==1) updata(1,1,n,x,y);
            else printf("%lld
    ",query(1,1,n,x,y));
        }
        return 0;
    }
    /*
    #          42607112 
    When       2018-09-07 11:38:57 
    Who        PotremZ 
    Problem    F - SUM and REPLACE
    Lang       GNU C++11 
    Verdict    Accepted
    Time       467 ms
    Memory     35000 KB
    */
    
  • 相关阅读:
    海思HI3516A开发板顺利上线
    android WIFI信息获取
    五------Jsp九大内置对象。
    在Windows下搭建Apacheserver
    基于ContentObserver来动态取消或加入屏幕超时任务
    使用Intent的Flag设置启动參数
    IntelliJ IDEA像Eclipse一样打开多个项目
    怎样让IE支持自己定义协议
    《TCP/IP具体解释卷2:实现》笔记--协议控制块
    POJ2029:Get Many Persimmon Trees(二维树状数组)
  • 原文地址:https://www.cnblogs.com/PotremZ/p/CF920F.html
Copyright © 2011-2022 走看看