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

来源:互联网 发布:淘宝开店简介怎么写 编辑:程序博客网 时间:2024/05/02 02:39

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5556


题意:定义一种Nico数,给出三种操作:

1.询问[L, R]内有多少个Nico数

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

3.将第K个数换成X


思路:打表可知满足Nico数定义的有:素数,2的幂,6,可以先预处理出这些数,对于1,3操作线段树都好处理,对于2操作,可以维护区间最大值,因为对于每一个数x取模的次数都不会超过log(x)次,如果当前区间最大值 < 取模值v,那就不必更新了


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 100010;const int INF = 0x3f3f3f3f;typedef long long ll;int pri[10000005];bool vis[10000005];void init(){    memset(vis, 0, sizeof(vis));    memset(pri, 0, sizeof(pri));    for (int i = 2; i <= 10000000; i++)    {        if (!pri[i]) pri[++pri[0]] = i;        for (int j = 1; j <= pri[0] && pri[j] <= 10000000 / i; j++)        {            pri[pri[j] * i] = 1;            if (i % pri[j] == 0) break;        }    }    for (int j = 1; j <= pri[0]; j++)        vis[pri[j]] = 1;    vis[0] = vis[1] = vis[6] = 1;    for (int i = 2; i <= 10000000; i *= 2)        vis[i] = 1;}int ma[MAXN << 2], num[MAXN << 2];void pushup(int rt){    ma[rt] = max(ma[rt << 1], ma[rt << 1 | 1]);    num[rt] = num[rt << 1] + num[rt << 1 | 1];}void build(int l, int r, int rt){    if (l == r)    {        scanf("%d", &ma[rt]);        if (vis[ma[rt]])            num[rt] = 1;        else            num[rt] = 0;        return ;    }    int mid = (l + r) >> 1;    build(lson);    build(rson);    pushup(rt);}void update1(int ql, int qr, int c, int l, int r, int rt){    if (ql > r || qr < l) return ;    if (ma[rt] < c) return ;    if (l == r)    {        ma[rt] %= c;        if (vis[ma[rt]])            num[rt] = 1;        else            num[rt] = 0;        return ;    }    int mid = (l + r) >> 1;    update1(ql, qr, c, lson);    update1(ql, qr, c, rson);    pushup(rt);}void update2(int p, int c, int l, int r, int rt){    if (l == p && r == p)    {        ma[rt] = c;        if (vis[c])            num[rt] = 1;        else            num[rt] = 0;        return ;    }    int mid = (l + r) >> 1;    if (p <= mid)        update2(p, c, lson);    else        update2(p, c, rson);    pushup(rt);}int query(int ql, int qr, int l, int r, int rt){    if (ql > r || qr < l) return 0;    if (ql <= l && qr >= r)        return num[rt];    int res = 0, mid = (l + r) >> 1;    res += query(ql, qr, lson);    res += query(ql, qr, rson);    return res;}int main(){    init();    int n;    while (~scanf("%d", &n))    {        build(1, n, 1);        // for (int i = 1; i <= n; i++)        //     printf("%d ", num[i]);        int m;        scanf("%d", &m);        while (m--)        {            int ch;            scanf("%d", &ch);            if (ch == 1)            {                int l, r;                scanf("%d%d", &l, &r);                printf("%d\n", query(l, r, 1, n, 1));            }            else if (ch == 2)            {                int l, r, c;                scanf("%d%d%d", &l, &r, &c);                update1(l, r, c, 1, n, 1);            }            else            {                int p, c;                scanf("%d%d", &p, &c);                update2(p, c, 1, n, 1);            }        }    }    return 0;}


0 0