题目链接
题目背景
题目名称是吸引你点进来的
实际上该题还是很水的
题目描述
区间质数个数
输入输出格式
输入格式:
一行两个整数 询问次数n,范围m
接下来n行,每行两个整数 l,r 表示区间
输出格式:
对于每次询问输出个数 t,如l或r∉[1,m]输出 Crossing the line
说明
【数据范围和约定】
对于20%的数据 1<=n<=10 1<=m<=10
对于100%的数据 1<=n<=1000 1<=m<=1000000 -10^9<=l<=r<=10^9 1<=t<=1000000
题解
由于涉及到区间查询操作,这道题我使用埃筛+线段树来做
我使用毒瘤的动态开点的方式进行建树操作
首先在建树前进行一次筛选,得到一张质数表,再根据质数表建树,如下
1 void GetList(int m){ 2 for(int i=2;i<=m;i++) 3 Prime[i]=true; 4 Prime[0]=false; 5 Prime[1]=false; 6 for(int i=2;i<=m;i++){ 7 if(!Prime[i]) 8 continue; 9 else 10 for(int j=i*2;j<=m;j+=i) 11 Prime[j]=false; 12 } 13 } 14 15 void Build(int &now,int l,int r,int x,int k){ 16 if(now==0) 17 now=++cnt; 18 if(l==r){ 19 Seg[now].sum=k; 20 return; 21 } 22 int mid=(l+r)>>1; 23 if(x<=mid) 24 Build(Seg[now].L,l,mid,x,k); 25 else 26 Build(Seg[now].R,mid+1,r,x,k); 27 Seg[now].sum=Seg[Seg[now].L].sum+Seg[Seg[now].R].sum; 28 } 29 30 GetList(m); 31 for(int i=1;i<=m;i++) 32 if(Prime[i]==true) 33 Build(root,1,m,i,1);//如果是质数,就把该点标记为1 34 else 35 Build(root,1,m,i,0);//如果不是质数,就标记为0
建树时这样操作,查询就可以和普通的线段树一样维护了
下面是完整代码
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 struct node{ 6 int sum; 7 int L; 8 int R; 9 }Seg[4000010]; 10 int root,cnt,n,m; 11 bool Prime[1000010]; 12 13 void GetList(int m){ 14 for(int i=2;i<=m;i++) 15 Prime[i]=true; 16 Prime[0]=false; 17 Prime[1]=false; 18 for(int i=2;i<=m;i++){ 19 if(!Prime[i]) 20 continue; 21 else 22 for(int j=i*2;j<=m;j+=i) 23 Prime[j]=false; 24 } 25 } 26 27 void Build(int &now,int l,int r,int x,int k){ 28 if(now==0) 29 now=++cnt; 30 if(l==r){ 31 Seg[now].sum=k; 32 return; 33 } 34 int mid=(l+r)>>1; 35 if(x<=mid) 36 Build(Seg[now].L,l,mid,x,k); 37 else 38 Build(Seg[now].R,mid+1,r,x,k); 39 Seg[now].sum=Seg[Seg[now].L].sum+Seg[Seg[now].R].sum; 40 } 41 42 int Query(int now,int l,int r,int x,int y){ 43 if(x<=l && r<=y) 44 return Seg[now].sum; 45 int mid=(l+r)>>1; 46 int sumL=0,sumR=0; 47 if(x<=mid) 48 sumL+=Query(Seg[now].L,l,mid,x,y); 49 if(y>mid) 50 sumR+=Query(Seg[now].R,mid+1,r,x,y); 51 return sumL+sumR; 52 } 53 54 int main(){ 55 scanf("%d%d",&n,&m); 56 GetList(m); 57 for(int i=1;i<=m;i++) 58 if(Prime[i]==true) 59 Build(root,1,m,i,1); 60 else 61 Build(root,1,m,i,0); 62 for(int i=1;i<=n;i++){ 63 register int p,q; 64 scanf("%d%d",&p,&q); 65 if(p<1 || p>m || q<1 || q>m) 66 printf("Crossing the line\n"); 67 else 68 printf("%d\n",Query(root,1,m,p,q)); 69 } 70 return 0; 71 }
友情链接:安利一只小姐姐的博客