ZOJ 3886 Nico Number(线段树单点更新+找规律)
2015-08-10 16:33
316 查看
题意:
定义一个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次幂,第三种是62、可以建一个一张表,直接标记某个数是不是NicoNico-number
3、使用线段树维护一段区间的NicoNico-number个数,然后可以进行对某一个数的修改,和对一个区间的查询。
关键对于第二种操作。我们要知道对于一个数x取余操作,最多会执行log(x)次,因为每次取余至少数值会减少一半,所以对于每个数来说最多会有log(x)次操作,之后会因为v大于当前值,而不用执行操作。
既然取余的次数不多,那么就可以对区域操作进行暴力,维护一段区间的最大值,如果最大值小于v,那么这一段不用更新,否则就遍历的最低层进行取余。
4、对于n个数来说,查找到一个数需要log(n),一个数最多会被修改log(x)次,所以总的时间不会超过n∗log(n)∗log(x)n*log(n)*log(x)。
mymy codecode
[code]#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, R using 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; }
相关文章推荐
- iOS计算缓存大小、清除缓存
- 查找组成一个偶数最接近的两个素数
- Django中的request.GET和request.POST
- IOS开发判断是否第一次使用软件且下次app自动更新后再次打开还是第一次使用
- CDN服务上线,DNSPOD布局云端生态圈
- linux shell 字符串操作(长度,查找,替换)详解
- HDOJ-2002-计算球体积
- POJ3264Balanced Lineup【RMQ模板】
- R 正则表达式例子
- 水管工游戏
- windows下的host文件在哪里,有什么作用?
- mysqldump参数之-d -t -T
- TS通过UDP的方式传送给VLC(下面为服务端代码),客服端接收方式:udp://@:5678
- STM3216位编码器溢出问题
- 零基础学python-2.1 输出 print()
- Makefile基础
- hdu 2087剪花布条 (KMP入门 子串出现的次数和子串个数)
- 零基础学python-2.1 输出 print()
- 素数问题
- TestNG监听器实现失败自动截图、重跑、自定义html结果文件功能