zoukankan      html  css  js  c++  java
  • 题解 CF920F 【SUM and REPLACE】

    题目描述

    维护一个长度为(n)序列,支持对一段区间将其所有元素换成其正约数个数,支持区间求和,(m)组询问

    对于(1le n,mle 3 imes 10^5),对于序列元素(1le a_{i}le 10^6)

    解题思路

    一看维护区间修改区间求和想到线段树,区间求和很好办,但是第一个貌似很棘手,考虑正约数个数( au)是一个积性函数,数据范围(1le a_{i}le 10^6),因此我们可以用线性筛将最大元素内的所有( au)值筛出来然后修改时候直接修改即可。

    这样暴力修改部分点会(T),但是卡卡常数貌似可过。

    考虑我们什么操作是多余的,对于一段区间,若是全为(1)(2),我们在修改的时候可以直接跳过,因此再维护一个区间最大值,修改的时候若最大值小于(3)直接忽略就可以

    (egin{aligned}mathcal{Code}end{aligned})

    #include<bits/stdc++.h>
        
    #define LL long long
        
    #define _ 0
        
    using namespace std;
        
    /*Grievous Lady*/
        
    const int BUF_SIZE = 1 << 12;
        
    char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
        
    #define PTR_NEXT() 
    { 
        buf_s ++; 
        if(buf_s == buf_t) 
        { 
            buf_s = buf; 
            buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); 
        } 
    }
        
    template <typename _m_> void mian(_m_ & _n_){
        int _x_ = 0 , _nega_ = 0;
        while(*buf_s != '-' && !isdigit(*buf_s)) PTR_NEXT(); if(*buf_s == '-'){_nega_ = 1; PTR_NEXT();}
        while(isdigit(*buf_s)){_x_ = _x_ * 10 + *buf_s - '0'; PTR_NEXT();} if(_nega_) _x_ = -_x_; (_n_) = (_x_);
    }
        
    const int kato = 1e6 + 10;
    
    int prime[kato] , tau[kato] , num[kato];
    
    LL cnt , max_;
    
    bool ispri[kato];
    
    inline void pri(int n){
        for(int i = 2;i <= n;i ++){
            if(!ispri[i]){
                prime[++ cnt] = i;
                num[i] = 1;
                tau[i] = 2;
            }
            for(int j = 1;j <= cnt && i * prime[j] <= n;j ++){
                ispri[i * prime[j]] = 1;
                if(i % prime[j] == 0){
                    num[i * prime[j]] = num[i] + 1;
                    tau[i * prime[j]] = tau[i] / num[i * prime[j]] * (num[i * prime[j]] + 1);
                    break;
                }
                num[i * prime[j]] = 1;
                tau[i * prime[j]] = tau[i] * tau[prime[j]];
            }
        }
    }
    
    struct tree{
        protected:
    
            struct node{
                node *ch[2];
                int l , r;
                LL sum , tag;
                node(int l = 0 , int r = 0 , LL sum = 0 , LL tag = 0): l(l) , r(r) , sum(sum) , tag(tag){
                    ch[0] = ch[1] = NULL;
                }
                inline int mid(){
                    return (l + r) >> 1;
                }
                inline void up(){
                    sum = ch[0] -> sum + ch[1] -> sum;
                    tag = max(ch[0] -> tag , ch[1] -> tag);
                }
            }*root;
    
            inline void build(node *&o , int l , int r){
                o = new node(l , r);
                if(l == r){
                    mian(o -> sum);
                    o -> tag = o -> sum;
                    max_ = max(o -> sum , max_);
                    return;
                }
                build(o -> ch[0] , l , o -> mid()); build(o -> ch[1] , o -> mid() + 1 , r);
                o -> up();
            }
    
            inline void Modify(node *o , int l , int r){
                if(o -> tag < 3) return;
                if(o -> l == o -> r){
                    o -> tag = o -> sum = tau[o -> sum];
                    return;
                }
                if(l <= o -> mid()){
                    Modify(o -> ch[0] , l , r);
                }
                if(r > o -> mid()){
                    Modify(o -> ch[1] , l , r);
                }
                o -> up();
            }
    
            inline LL ask(node *o , int l , int r){
                // if(o -> l > r || o -> r < l) return 0;
                if(l <= o -> l && o -> r <= r){
                    return o -> sum;
                }
                LL res = 0;
                if(l <= o -> mid()){
                    res += ask(o -> ch[0] , l , r);
                }
                if(r > o -> mid()){
                    res += ask(o -> ch[1] , l , r);
                }
                return res;
            }
            
        public:
    
            inline void build(int n){
                build(root , 1 , n);
            }
    
            inline void Modify(int l , int r){
                Modify(root , l , r);
            }
    
            inline LL ask(int l , int r){
                return ask(root , l , r);
            }
    }yuni;
    
    int n , m , opt , l , r;
    
    inline int Ame_(){
        mian(n) , mian(m);
        yuni.build(n);
        tau[1] = 1;
        pri(max_);
        for(; m --> 0 ;){
            mian(opt) , mian(l) , mian(r);
            if(opt == 1) yuni.Modify(l , r);
            if(opt == 2) printf("%lld
    " , yuni.ask(l , r));
        }
        return ~~(0^_^0);
    }
        
    int Ame__ = Ame_();
        
    int main(){;}
    

    -----(egin{aligned}mathcal{Ame}end{aligned})__

  • 相关阅读:
    机器学习十讲----第五讲
    Python数据挖掘学习进度06(numpy基本操作2、数组间运算)
    深度学习进度02(图和tensorboard、op、会话、张量)
    机器学习十讲----第四讲
    机器学习十讲----第三讲
    机器学习十讲----第二讲
    元胞自动机
    RuntimeError: The Session graph is empty. Add operations to the graph before calling run().解决方法
    Python数据挖掘学习进度05(numpy基本操作)
    深度学习进度01(深度和机器的区别、tensorflow的使用-tf数据流图)
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/13747827.html
Copyright © 2011-2022 走看看