posted on 2021-07-10 20:00:18 | under 题解 | source

观察题目,发现它说了这么多其实是想让我们写一个数据结构支持:

  • 单点修改(区间长为 \(1\) 的区间修改);
  • 区间赋值;
  • 区间计算 \(<10^7\) 的素数个数。

看到”区间赋值”这个操作,我们不难想到 Old Driver Tree 这一暴力数据结构。本题数据较水,所以使用 Old Driver Tree 是可以通过的,大胆去写吧。

另外,题目已经说了素数最大 \(10^7\),为了更容易通过,最好使用线性筛预处理出所有素数,然后每次 \(O(1)\) 判断素数。

下面给出我的代码实现:

#include <set>
#include <iostream>
#include <algorithm>
using namespace std;
template<int N> struct LS{//线性筛板子
	//https://www.luogu.com.cn/blog/cicos/notprime
    int p[N+10],n;
    bool isnp[N+10];
    LS(){
        isnp[0]=isnp[1]=1;
        for(int i=2;i<=N;i++){
            if(!isnp[i]) p[++n]=i;
            for(int j=1;j<=n&&i*p[j]<=N;j++){
                if(isnp[i*p[j]]=1,i%p[j]==0) break; 
                //上面这个是逗号表达式,固定从左往右,返回最后一个值
            }
        }
    }
    bool operator()(int x){return !isnp[x];}
};
LS<10000000> p;
//  1234567 个 0 别数错了
template<class T> struct ODT{
    struct node{
        int l,r;
        mutable T v;
        operator int()const{return r-l+1;}
        //https://zh.cppreference.com/w/cpp/language/cast_operator
        //注意 const 不能少
        node(int l,int r=-1,T v=0):l(l),r(r),v(v){}
        bool operator<(const node &b)const{return l<b.l;}
    }; 
    set<node> s;
    typedef typename set<node>::iterator IT;
    void init(int n,T a[]){
        s.insert(node(n+1,n+1));
        for(int i=1;i<=n;i++) s.insert(node(i,i,a[i]));
    }
    IT split(int pos){
        IT it=s.lower_bound(node(pos));
        if(it!=s.end()&&it->l==pos) return it;
        T v=(--it)->v;
        //如果你像我一样压行,一定要注意优先级问题,--it 加一对括号
        int l=it->l,r=it->r;
        s.erase(it);
        s.insert(node(l,pos-1,v));
        return s.insert(node(pos,r,v)).first;
    }
    void assign(int l,int r,T v){
        IT R=split(r+1),L=split(l);
        s.erase(L,R);
        s.insert(node(l,r,v));
    }
    void add(int l,int r,T v){
        IT R=split(r+1),L=split(l);
        for(IT it=L;it!=R;++it) it->v+=v;
    }
    int query(int l,int r){
        int ans=0;
        IT R=split(r+1),L=split(l);
        for(IT it=L;it!=R;++it) ans+=p(min(it->v,10000000))*(*it);
        //同样 (*it) 的括号也不能少
        return ans;
    }
    void output(){
        for(IT it=s.begin();it!=s.end();++it){
            for(int i=it->l;i<=it->r;i++){
                cout<<it->v<<" |"[i==it->r];
            }
        }
        cout<<endl;
    }
};
ODT<int> a;
int n,m,ipu[100010];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>ipu[i];
    a.init(n,ipu);
    for(int i=1;i<=m;i++){char op;
        cin>>op;
        //或 scanf(" %c",&op),注意空格
        if(op=='A'){
            int l,v;
            cin>>v>>l;//注意输入格式
            a.add(l,l,v);
        }else if(op=='R'){
            int l,r,v;
            cin>>v>>l>>r;
            a.assign(l,r,v);
        }else{
            int l,r;
            cin>>l>>r;
            cout<<a.query(l,r)<<endl;
        }
        //a.output();
    }
    return 0;
}

原文地址:http://www.cnblogs.com/caijianhong/p/solution-SP19568.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性