ZOJ 题目3911 Prime Query(线段树求区间素数个数)

Prime Query

Time Limit: 1 Second       Memory Limit: 196608 KB

You are given a simple task. Given a sequence A[i] with N numbers. You have to perform Q operations on the given sequence.

Here are the operations:

  • A v l, add the value v to element with index l.(1<=V<=1000)
  • R a l r, replace all the elements of sequence with index i(l<=i<= r) with a(1<=a<=10^6) .
  • Q l r, print the number of elements with index i(l<=i<=r) and A[i] is a prime number

Note that no number in sequence ever will exceed 10^7.

Input

The first line is a signer integer T which is the number of test cases.

For each test case, The first line contains two numbers N and Q (1 <= N, Q <= 100000) - the number of elements in sequence and the number of queries.

The second line contains N numbers - the elements of the sequence.

In next Q lines, each line contains an operation to be performed on the sequence.

Output

For each test case and each query,print the answer in one line.

Sample Input
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
Sample Output
2
1
2
4
0

4

题目大意:一个序列,n个数,m个操作,A表示第x个位置的数上边加y,R x y z,表示x到y区间内的数变成z,Q表示查询x y,区间内素数的个数

ac代码

<pre name="code" class="cpp">#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>

#define LL long long
using namespace std;
bool isp[1000005];
int p[1000005],top;
struct s
{
    int sum,cover,num;
}node[100005<<2];
void init()
{
    top=0;
    memset(isp,true,sizeof(isp));
    for(int i=2;i<1000005;i++)
    {
        if(isp[i])
            p[top++]=i;
        for(int j=0;j<top&&(LL)i*p[j]<1000005;j++)
        {
            isp[i*p[j]]=false;
            if(!i%p[j])
                break;
        }
    }
}
void pushup(int tr)
{
    node[tr].sum=node[tr<<1].sum+node[tr<<1|1].sum;
}
void pushdown(int tr,int m)
{
    if(node[tr].cover)
    {
        node[tr<<1].cover=node[tr].cover;
        node[tr<<1|1].cover=node[tr].cover;
        node[tr<<1].sum=(m-(m>>1))*isp[node[tr].cover];
        node[tr<<1|1].sum=(m>>1)*isp[node[tr].cover];
        node[tr<<1].num=node[tr].cover;
        node[tr<<1|1].num=node[tr].cover;
        node[tr].cover=0;
    }
}
void build(int l,int r,int tr)
{
    node[tr].cover=0;
    if(l==r)
    {
        scanf("%d",&node[tr].num);
        node[tr].sum=isp[node[tr].num];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,tr<<1);
    build(mid+1,r,tr<<1|1);
    pushup(tr);
}
int ISP(int val)//快速判断是不是素数
{
    if((val&1)==0)
        return 0;
    int num=val;
    for(int i=0;i<top&&(LL)p[i]*p[i]<=val;i++)
    {
        while(val%p[i]==0)
        {
            val/=p[i];
        }
    }
    return num==val;
}
void add(int pos,int val,int l,int r,int tr)
{
    if(l==r)
    {
        node[tr].num+=val;
        node[tr].sum=ISP(node[tr].num);
        return;
    }
    pushdown(tr,r-l+1);
    int mid=(l+r)>>1;
    if(pos<=mid)
        add(pos,val,l,mid,tr<<1);
    else
        add(pos,val,mid+1,r,tr<<1|1);
    pushup(tr);
}
void update(int L,int R,int val,int l,int r,int tr)
{
    if(L<=l&&r<=R)
    {
        node[tr].num=val;
        node[tr].cover=val;
        node[tr].sum=(r-l+1)*isp[val];
        return;
    }
    pushdown(tr,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)
        update(L,R,val,l,mid,tr<<1);
    if(R>mid)
        update(L,R,val,mid+1,r,tr<<1|1);
    pushup(tr);
}
int query(int L,int R,int l,int r,int tr)
{
    if(L<=l&&r<=R)
    {
        return node[tr].sum;
    }
    pushdown(tr,r-l+1);
    int mid=(l+r)>>1;
    /*if(R<=mid)
        return query(L,R,l,mid,tr<<1);
    else
        if(L>mid)
            return query(L,R,mid+1,r,tr<<1|1);
        else
            return query(L,mid,l,mid,tr<<1)+query(mid+1,R,mid+1,r,tr<<1|1);*/
    int a,b;
    a=0;
    b=0;
    if(L<=mid)
        a=query(L,R,l,mid,tr<<1);
    if(R>mid)
        b=query(L,R,mid+1,r,tr<<1|1);
    return a+b;
}
char op[10];
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        build(1,n,1);
        while(q--)
        {
            scanf("%s",op);
            if(op[0]=='A')
            {
                int x,y;
                scanf("%d%d",&x,&y);
                add(y,x,1,n,1);
            }
            else
                if(op[0]=='R')
                {
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    update(y,z,x,1,n,1);
                }
                else
                    if(op[0]=='Q')
                    {
                        int x,y;
                        scanf("%d%d",&x,&y);
                        //scanf("%d%d",&x,&y);
                        printf("%d\n",query(x,y,1,n,1));
                    }
        }
    }
    return 0;
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值