zoukankan      html  css  js  c++  java
  • CF920F SUM and REPLACE(线段树+思维)

    这题比较套路,首先我们发现,区间变成约数个数是不可能用区间维护的,因此这题显然有个trick

    既然只能暴力修改单点,但是我们又要要求修改次数不能太多,因此可以联想到,是不是我约数个数求几次就变成一个常数了

    继续观察,果然是这样,因此我们发现修改次数不会太多

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=1e6+10;
    const int mod=1e9+7;
    int a[N];
    struct node{
        int l,r;
        int cnt;
        ll sum;
    }tr[N<<2];
    bool mark[N];
    int prim[N],d[N],num[N];
    int cnt;
    void initial(){
        cnt=0;
        d[1]=1;
        for (int i=2;i<N;++i){
            if (!mark[i]){
                prim[cnt++]=i;
                num[i]=1;
                d[i]=2;
            }
            for (int j=0;j<cnt&&i*prim[j]<N;++j){
                mark[i*prim[j]]=1;
                if (!(i%prim[j])){
                    num[i*prim[j]]=num[i]+1;
                    d[i*prim[j]]=d[i]/(num[i]+1)*(num[i*prim[j]]+1);
                    break;
                }
                d[i*prim[j]]=d[i]*d[prim[j]];
                num[i*prim[j]]=1;
            }
        }
    }
    void pushup(int u){
        tr[u].cnt=tr[u<<1].cnt+tr[u<<1|1].cnt;
        tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r,a[l]==1,a[l]};
        }
        else{
            tr[u]={l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            pushup(u);
        }
    }
    void modify(int u,int l,int r){
        ll x=tr[u].r-tr[u].l+1-tr[u].cnt;
        if(tr[u].sum-tr[u].cnt==x*2)
            return ;
        if(tr[u].l==tr[u].r){
            tr[u].sum=d[tr[u].sum];
            tr[u].cnt=(tr[u].sum==1)?1:0;
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,r);
        if(r>mid)
            modify(u<<1|1,l,r);
        pushup(u);
    }
    ll query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].sum;
        }
        int mid=tr[u].l+tr[u].r>>1;
        ll ans=0;
        if(l<=mid)
            ans+=query(u<<1,l,r);
        if(r>mid)
            ans+=query(u<<1|1,l,r);
        return ans;
    }
    int main(){
        ios::sync_with_stdio(false);
        int n,m;
        cin>>n>>m;
        int i;
        initial();
        for(i=1;i<=n;i++){
            cin>>a[i];
        }
        build(1,1,n);
        while(m--){
            int opt;
            cin>>opt;
            int l,r;
            cin>>l>>r;
            if(opt==1){
                modify(1,l,r);
            }
            else{
                cout<<query(1,l,r)<<endl;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    项目目标文档
    河北省民间组织管理系统项目分析
    《探索需求》读书笔记一
    “花儿日记”项目总结
    2015年秋季个人阅读计划
    场景调研
    “数组最大值求和”结对情况
    课堂改进意见
    《梦断代码》阅读笔记三
    linux io 学习笔记(03)---共享内存,信号灯,消息队列
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14097102.html
Copyright © 2011-2022 走看看