ZOJ 3886 Nico Number(线段树单点更新+找规律)
来源:互联网 发布:国外域名购买代理商 编辑:程序博客网 时间:2024/05/02 04:22
题意:
定义一个NicoNico-number,如果x是NicoNico-number,那么所有小于x的且与x互质的整数是一个等差数列,初始给出n个数字的数组,三种操作:
1 l r 问在[l,r]内有多少个NicoNico-number数
2 l r v 对于[l,r]内的数全部对v取余
3 k x 将第k个数换为x
对每一次询问做出输出。
解析(转):
1、首先写一个找规律的程序,发现NicoNico-number是有三种组成的第一种是素数,第二种是2的x次幂,第三种是6
2、可以建一个一张表,直接标记某个数是不是NicoNico-number
3、使用线段树维护一段区间的NicoNico-number个数,然后可以进行对某一个数的修改,和对一个区间的查询。
关键对于第二种操作。我们要知道对于一个数x取余操作,最多会执行log(x)次,因为每次取余至少数值会减少一半,所以对于每个数来说最多会有log(x)次操作,之后会因为v大于当前值,而不用执行操作。
既然取余的次数不多,那么就可以对区域操作进行暴力,维护一段区间的最大值,如果最大值小于v,那么这一段不用更新,否则就遍历的最低层进行取余。
4、对于n个数来说,查找到一个数需要log(n),一个数最多会被修改log(x)次,所以总的时间不会超过
#pragma comment(linker, "/STACK:102400000,102400000")#include <cstdio>#include <cstring>#include <algorithm>#define ls (o<<1)#define rs (o<<1|1)#define lson ls, L, M#define rson rs, M+1, Rusing namespace std;const int MAXX = (int)1e7 + 5;const int MAXN = (int)1e5 + 5;bool nico[MAXX*2];int A[MAXN];int n, q;void prepare() { memset(nico, true, sizeof(nico)); for(int i = 2; i < MAXX; i++) { if(!nico[i]) continue; nico[i] = true; for(int j = i*2; j < MAXX; j += i) { nico[j] = false; } } nico[6] = true; for(int i = 1; i < MAXX; i <<= 1) { nico[i] = true; }}int maxv[MAXN << 2], sumv[MAXN << 2];void pushUp(int o) { maxv[o] = max(maxv[ls], maxv[rs]); sumv[o] = sumv[ls] + sumv[rs];}void build(int o, int L, int R) { if(L == R) { maxv[o] = A[L]; sumv[o] = nico[A[L]]; return ; } int M = (L + R)/2; build(lson); build(rson); pushUp(o);}int query(int o, int L, int R, int ql, int qr) { if(ql <= L && R <= qr) return sumv[o]; int M = (L + R)/2, ret = 0; if(ql <= M) ret += query(lson, ql, qr); if(qr > M) ret += query(rson, ql, qr); return ret;}void setValue(int o, int L, int R, int pos, int val) { if(L == R) { sumv[o] = nico[val]; maxv[o] = val; return ; } int M = (L + R)/2; if(pos <= M) setValue(lson, pos, val); else setValue(rson, pos, val); pushUp(o);}void modify(int o, int L, int R, int ql, int qr, int val) { if(ql <= L && R <= qr && val > maxv[o]) return ; if(L == R) { maxv[o] %= val; sumv[o] = nico[maxv[o]]; return ; } int M = (L + R)/2; if(ql <= M) modify(lson, ql, qr, val); if(qr > M) modify(rson, ql, qr, val); pushUp(o);}int main() { prepare(); while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; i++) { scanf("%d", &A[i]); } build(1, 1, n); scanf("%d", &q); int oper, ql, qr, val; while(q--) { scanf("%d", &oper); if(oper == 1) { scanf("%d%d", &ql, &qr); printf("%d\n", query(1, 1, n, ql, qr)); }else if(oper == 2) { scanf("%d%d%d", &ql, &qr, &val); modify(1, 1, n, ql, qr, val); }else { scanf("%d%d", &ql, &val); setValue(1, 1, n, ql, val); } } } return 0;}
0 0
- ZOJ 3886 Nico Number(线段树单点更新+找规律)
- ZOJ 3886 Nico number(线段树)
- ZOJ 3886 Nico Number (线段树)
- 【ZOJ】3886 Nico Number【线段树】
- ZOJ 3886 Nico Number(素数筛选 + 线段树)
- zoj 3886 Nico Number(线段树,区间取模操作)
- ZOJ 3886 Nico Number
- zoj3886--Nico Number(素数筛+线段树)
- ZOJ-#3622 Magic Number(找规律)
- zoj 3622 Magic Number(找规律)
- ZOJ 3886 Nico Number(筛素数+Love(线)Live(段)树)
- ZOJ 3279 Ants(线段树单点更新和查询)
- zoj (单点更新区间查询:线段树)
- zoj 3772 线段树--单点更新
- zoj 3279 Ants (线段树单点更新)
- ZOJ 1484 HDU 1394 Minimum Inversion Number / 线段树单点更新
- HDU1394-Minimum Inversion Number(线段树单点更新)
- hdu 1394 Minimum Inversion Number(线段树单点更新)
- Django中的request.GET和request.POST
- 重构与模式--简化
- 查找组成一个偶数最接近的两个素数
- Centos 6.5 下安装 Matlab R2010a
- 树状数组
- ZOJ 3886 Nico Number(线段树单点更新+找规律)
- Java的String类中常用方法举例
- Java8之Stream(1)
- HDU 2094 产生冠军 map
- JavaMail简单入门案例
- 自考本科全日制要怎么度过
- Linux shell脚本执行方式:source、sh、bash、./执行脚本的区别
- 租车系统
- 自定义Spinner--可以默认不选中,修改默认显示的spinner