ZOJ 3886 Nico Number(筛素数+Love(线)Live(段)树)

problemCode=3886">ZOJ 3886

题意:

定义一种NicoNico数x,x有下面特征:

全部不大于x且与x互质的数成等差数列,如x = 5 ,与5互素且不大于5的数1,2,3,4成等差数列。则5是一个NicoNico数。

再定义三种操作:

1.南小鸟询问[L, R]内有多少个NicoNico数;

2.果皇把[L, R]内的数全部对v取余;

3.果皇将第K个数换成X。

然后给你一个数列,并对这个数列运行若干操作

思路:

这样的问题果断要用LoveLive树线段树来做!

首先我们通过打表发现NicoNico数仅仅可能是素数。2的n次幂。6,所以能够先预处理,对范围内的全部NicoNico数进行标记。

建树过程:假设是NicoNico数则节点值为1,不是则为0。

更新操作1:对区间内的数进行取模即是区间改动。这里能够优化一下,假设区间最大值小于v,则不须要改动。

更新操作2:即单点改动。

查询操作:输出询问区间和就可以。

时间复杂度:

预处理:O(x)

建树:O(n)

查询与更新:操作次数O(m),每次操作O(logn)加起来是O(mlogn)

羞耻的代码君:

这次代码风格。

重在理解重在理解。

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
#define lson l , mid , root << 1
#define rson mid + 1 , r , root << 1 | 1
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxNico = 1e7 + 500 ;
const int maxHonoka = 1e5 + 7 ;
int Honoka_max[10 * maxHonoka] ;
int Honoka_sum[10 * maxHonoka] ;
bool Nico_prime[maxNico];
map<int , int> NicoNicoNi;

/* にっこにっこにー☆あなたのハートににこにこにー 笑颜届ける矢澤にこにこー にこにーって覚えてラブにこー */

void init(){
    NicoNicoNi[0] = NicoNicoNi[6] = 1;
    for( int i = 0 ; i <= 31 ; i++ ){
        NicoNicoNi[( 1 << i )] = 1;
    }
    cls( Nico_prime );
    for( int  i = 2 ; i * i <= maxNico ; i++ ){
        if( !Nico_prime[i] )
            for( int j = i * i ; j <= maxNico ; j+=i )
                Nico_prime[j] = 1;
    }
    for( int i = 2 ; i <= maxNico ; i++ )
        if( !Nico_prime[i] ) NicoNicoNi[i] = 1;
}

void push_Yazawa( int root ){
    Honoka_max[root] = max( Honoka_max[ root << 1 ] , Honoka_max[ root << 1 | 1 ] );
    Honoka_sum[root] = Honoka_sum[ root << 1 ] + Honoka_sum[ root << 1 | 1 ] ;
}

void build_Kotori( int l , int r , int root ){
    if( l == r ){
        scanf( "%d" , &Honoka_max[root] );

        if( NicoNicoNi[Honoka_max[root]] )
            Honoka_sum[root] = 1;
        else
            Honoka_sum[root] = 0;
        return ;
    }
    int mid = ( l + r ) / 2 ;
    build_Kotori( lson );
    build_Kotori( rson );
    push_Yazawa( root );
}

void Honoka1( int ql , int qr , int x , int l , int r , int root ){

    if( qr < l || ql > r )
        return ;
    if( Honoka_max[root] < x)
        return ;

    if( l == r ){
        Honoka_max[root] %= x ;

        if( NicoNicoNi[Honoka_max[root]] )
            Honoka_sum[root] = 1;
        else
            Honoka_sum[root] = 0;

        return ;
    }

    int mid = ( l + r ) / 2 ;
    Honoka1( ql , qr , x , lson );
    Honoka1( ql , qr , x , rson );
    push_Yazawa( root );
}

void Honoka2( int pos , int x , int l , int r , int root ){

    if( l == pos && r == pos ){
        Honoka_max[root] = x ;
        if( NicoNicoNi[x] )
            Honoka_sum[root] = 1;
        else
            Honoka_sum[root] = 0;
        return ;
    }

    int mid = ( l + r ) / 2 ;
    if( mid >= pos )
        Honoka2( pos , x , lson );
    else
        Honoka2( pos , x , rson );
    push_Yazawa( root );
}

int Kotori( int ql , int qr , int l , int r , int root ){

    if( ql > r || qr < l )
        return 0 ;
    if( ql <= l && qr >= r )
        return Honoka_sum[root];

    int res = 0 ;
    int mid = ( l + r ) / 2 ;
    if( ql <= mid )
        res += Kotori( ql , qr , lson ) ;
    if( qr > mid )
        res += Kotori( ql , qr , rson ) ;
    return res;
}
int main(){
  //freopen("input.txt","r",stdin);
    init();
    int n ;
    while( cin >> n ){
        build_Kotori( 1 , n , 1 ) ;
        int m ;
        cin >> m ;
        for( int i = 1 ; i <= m ; i++ ){
            int num ;
            scanf( "%d" , &num );
            if( num == 1 ){
                int left , right ;
                scanf( "%d%d" , &left , &right ) ;
                printf( "%d\n" , Kotori( left , right , 1 , n , 1 ));
            }
            else if( num == 2 ){
                int left , right , mod ;
                scanf( "%d%d%d" , &left , &right , &mod ) ;
                Honoka1( left , right , mod , 1 , n , 1 ) ;
            }
            else if( num == 3 ){
                int pos , x ;
                scanf( "%d%d" , &pos , &x ) ;
                Honoka2( pos , x , 1 , n , 1 ) ;
            }
        }
    }
    return 0;
}
时间: 2024-10-12 07:25:23

ZOJ 3886 Nico Number(筛素数+Love(线)Live(段)树)的相关文章

ZOJ 3886 Nico number(线段树)

Nico Number Time Limit: 2 Seconds      Memory Limit: 262144 KB Kousaka Honoka and Minami Kotori are playing a game about a secret of Yazawa Nico. When the game starts, Kousaka Honoka will give Minami Kotori an array A of N non-negative integers. Ther

ZOJ 3886 Nico Number (线段树)

题目地址:ZJU 3886 这个题需要想到一点,因为对一个数x不断取模的话,而且设定他小于模才会进行取余操作的话,那么最多只会进行logx次,因为每次取模都会使x最少折半.然后想到了这点就很好做了.对于区间取模更新操作可以直接暴力更新,维护一个最大值,如果这个区间的最大值小于模的话, 就不用继续向叶子更新了.然后其他的大于模的就更新到叶子节点. 然后对于NicoNumber来说,只有6,2的幂次和素数来说是符合的.所以可以预处理出来.然后就可以用线段树来维护了. 代码如下: #include <

zoj3886--Nico Number(素数筛+线段树)

Nico Number Time Limit: 2 Seconds      Memory Limit: 262144 KB Kousaka Honoka and Minami Kotori are playing a game about a secret of Yazawa Nico. When the game starts, Kousaka Honoka will give Minami Kotori an array A of N non-negative integers. Ther

POJ-2689 Prime Distance (两重筛素数,区间平移)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13961   Accepted: 3725 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

leetcode 204. Count Primes(线性筛素数)

Description: Count the number of prime numbers less than a non-negative number, n. 题解:就是线性筛素数的模板题. class Solution { public: int countPrimes(int n) { int ans=0; vector<int>is_prime(n+1,1); for(int i=2;i<n;i++){ if(is_prime[i]){ ans++; for(int j=2*

POJ 3048 Max Factor (筛素数)

Description To improve the organization of his farm, Farmer John labels each of his N (1 <= N <= 5,000) cows with a distinct serial number in the range 1..20,000. Unfortunately, he is unaware that the cows interpret some serial numbers as better tha

CF449C Jzzhu and Apples (筛素数 数论?

Codeforces Round #257 (Div. 1) C Codeforces Round #257 (Div. 1) E CF450E C. Jzzhu and Apples time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has picked n apples from his big apple tre

常见模板(欧拉筛素数,最小生成树,快排,并查集,单源最短路)

欧拉筛素数: #include<cstdio> #define maxn 10000000+10 using namespace std; int n,prime[5000001],num_prime=0,m; bool if_prime[maxn]; void euler(int limit) { for(int i=2;i<=limit;i++) { if(!if_prime[i]) prime[++num_prime]=i; for(int j=1;prime[j]*i<=l

洛谷 P3383 【模板】线性筛素数

P3383 [模板]线性筛素数 题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1且不大于N的整数,即询问概数是否为质数. 输出格式: 输出包含M行,每行为Yes或No,即依次为每一个询问的结果. 输入输出样例 输入样例#1: 100 5 2 3 4 91 97 输出样例#1: Yes Yes No No Yes 说明 时空限制:5