• [是题解哦] 洛谷 P1865 A % B Problem


    题目链接

    这里这里

    题目背景

    题目名称是吸引你点进来的

    实际上该题还是很水的

    题目描述

    区间质数个数

    输入输出格式

    输入格式:

    一行两个整数 询问次数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
    ");
    67         else
    68             printf("%d
    ",Query(root,1,m,p,q));
    69     }
    70     return 0;
    71 }


    友情链接:安利一只小姐姐的博客

  • 相关阅读:
    nodewebkit系列(00):什么是nodewebkit?
    浅析Chrome Packaged Apps
    C#实现飞信短信发送
    结束——2012年微软精英挑战赛
    Vue开发笔记 — Vue项目结构
    TOGAF
    笔记本安装CentOS8
    架构设计的10个核心原则
    Vue PDF文件预览vuepdf
    Druid中使用log4j2进行日志输出
  • 原文地址:https://www.cnblogs.com/tatarakogasa/p/9782870.html
Copyright © 2020-2023  润新知