题解 SP13015 【CNTPRIME - Counting Primes 】
Setsugesuka · · 题解
阅读题意,发现题目要求我们维护两种操作,区间推平与统计区间素数个数,数据范围很小,用裸的
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
struct node
{
int l,r,v;
node(int L,int R=-1,int V=0):l(L),r(R),v(V) {}
bool operator <(const node &o) const
{
return l<o.l;
}
};
int prime[MAXN],p[MAXN],tot=0;
set<node> s;
inline void init()
{
prime[1]=prime[0]=1;
for(int i=2;i<=MAXN-10;i++)
{
if(prime[i]==0)
p[++tot]=i;
for(int j=1;j<=tot&&i*p[j]<=MAXN-10;j++)
{
prime[i*p[j]]=1;
if(i%p[j]==0)
break;
}
}
}
inline set<node>::iterator split(int pos)
{
set<node>::iterator it=s.lower_bound(node(pos));
if(it!=s.end()&&it->l==pos) return it;
--it;
int L=it->l,R=it->r,V=it->v;
s.erase(it);
s.insert(node(L,pos-1,V));
return s.insert(node(pos,R,V)).first;
}
inline void assignval(int l,int r,int v)
{
set<node>::iterator itr=split(r+1),itl=split(l);
s.erase(itl,itr);
s.insert(node(l,r,v));
}
inline int query(int l,int r)
{
set<node>::iterator itr=split(r+1),itl=split(l);
int ret=0;
for(itl;itl!=itr;++itl)
{
if(!prime[itl->v])
ret+=(itl->r-itl->l+1);
}
return ret;
}
int n,m,t;
int main()
{
init();
scanf("%d",&t);
for(int cc=1;cc<=t;cc++)
{
printf("Case %d:\n",cc);
scanf("%d %d",&n,&m);
s.clear();
for(int i=1;i<=n;i++)
{
int sr;
scanf("%d",&sr);
s.insert(node(i,i,sr));
}
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int l,r,v;
scanf("%d %d %d",&l,&r,&v);
assignval(l,r,v);
}
else
{
int l,r;
scanf("%d %d",&l,&r);
printf("%d\n",query(l,r));
}
}
}
return 0;
}