SP19568 PRMQUER - Prime queries
PRMQUER - Prime queries
题面翻译
题目描述
这是一个简单的题目
给定
- 三个整数
表示给第 个数加上 。 - 四个整数
表示把区间 的数都变为 。 - 三个整数
表示询问区间 里,小于等于 的素数有多少个。
数据保证任何时刻这
数据范围
输入格式
第一行两个整数
输出格式
对于每个操作
题目描述
You are given a simple task.
Given a sequence A[i] with N numbers s.t. 1 <= i <= N. You have to perform Q operations on a given set of numbers.
Operations:
A V l
, Add the value V to element with index l.R a l r
, Replace all the elements of sequence with index i s.t. l <= i <= r with a.Q l r
, Print the Number of elements with index i s.t. l <= i <= r and A[i] is prime number and A[i] <= 10^7.
No Number In sequence ever will exceed 10^9.
输入格式
First line contains N as Number of sequence elements && Q as number of operations to be performed. Second line contains Initial N elements of the sequence. After that each of the next Q lines contains one operation to be performed on the sequence.
输出格式
Print each value in newline as stated above.
样例 #1
样例输入 #1
5 10
1 2 3 4 5
A 3 1
Q 1 3
R 5 2 4
A 1 1
Q 1 1
Q 1 2
Q 1 4
A 3 5
Q 5 5
Q 1 5
样例输出 #1
2
1
2
4
0
4
Solution
SP13015 双倍经验(甚至还少了单点修改的操作)
既然有区间推平的操作那就用珂朵莉树水一水吧(逃
区间推平操作是珂朵莉树自带的,所以就不在这里详细阐述了,先来看单点修改怎么做(我最开始看成区间加了所以用区间加实现的)。单点加可以看作一个长度为
然后是查询。注意到询问的质数范围是
另外需要注意的是,节点的
Code
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
template<typename T> void read(T &k)
{
k=0;T flag=1;char b=getchar();
while (!isdigit(b)) {flag=(b=='-')?-1:1;b=getchar();}
while (isdigit(b)) {k=k*10+b-48;b=getchar();}
k*=flag;
}
const int _MAXN=1e7,_SIZE=1e5;
bool prime[_MAXN+5];
void preWork()//埃筛
{
prime[1]=1;
for (int i=2;i<=_MAXN;i++)
if (!prime[i])
for (int j=2;j*i<=_MAXN;j++)
prime[j*i]=1;
}
struct NODE{//珂朵莉树
int l,r;
mutable int v;
NODE (int l,int r=0,int v=0) : l(l),r(r),v(v) {}
bool operator< (const NODE &a) const {return l<a.l;}
};
set <NODE> ctlt;
auto split(int pos)
{
auto it=ctlt.lower_bound(NODE(pos));
if (it!=ctlt.end() && it->l==pos) return it;
it--;
if (it->r<pos) return ctlt.end();
int l=it->l,r=it->r,v=it->v;
ctlt.erase(it);
ctlt.insert(NODE(l,pos-1,v));
return ctlt.insert(NODE(pos,r,v)).first;
}
void assign(int l,int r,int x)
{
auto itr=split(r+1),itl=split(l);
ctlt.erase(itl,itr);
ctlt.insert(NODE(l,r,x));
}
void modify(int l,int r,int v)//区间加(用于实现单点加)
{
auto itr=split(r+1),itl=split(l);
for (auto it=itl;it!=itr;it++) it->v+=v;
}
int query(int l,int r)//区间查询
{
auto itr=split(r+1),itl=split(l);
int res=0;
for (auto it=itl;it!=itr;it++)
if (it->v<=10000000 && !prime[it->v]) res+=it->r-it->l+1;//需要注意v值可能大于1e7,直接查看数组会导致下标越界,所以先进行判断
return res;
}
int n,q;
int a[_SIZE+5];
int main()
{
preWork();
read(n),read(q);
for (int i=1;i<=n;i++) read(a[i]),ctlt.insert(NODE(i,i,a[i]));//读入+建树
for (int i=1;i<=q;i++)
{
char op[2];scanf("%s",op);
if (op[0]=='A')
{
int pos,x;
read(x),read(pos);
modify(pos,pos,x);
}
else if (op[0]=='R')
{
int l,r,x;
read(x),read(l),read(r);
assign(l,r,x);
}
else
{
int l,r;
read(l),read(r);
printf("%d\n",query(l,r));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步