[luoguP2801] 教主的魔法(二分 + 分块)
传送门
以为对于这类问题线段树都能解决,分块比线段树菜,结果培训完才知道线段树是一种特殊的分块方法,有的分块的题线段树不能做,看来分块还是有必要学的。
对于这个题,先分块,然后另开一个数组对于每个块内排序。
区间加的话,加一个标记,每一个整块区间加,里面的数的相对大小不变,而左右两边零散的块直接暴力重构。
查询可以对于每个块二分查找。
时间复杂度应该是 nlogn + Q√nlog√n,刚好卡过。。
注意:第10个点会被卡,手写二分比stl的lower_bound快一点,可以避免被卡。
也可以在 S = sqrt(n) 后面 + x,x 不要太大也不要太小,不知道为什么,速度也会快点,玄学啊。
%%%有些dalao不知道怎么写的,1000ms
——代码(最终只能优化到1600ms)
1 #include <cmath> 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 #define LL long long 6 7 const int MAXN = 1000001; 8 int n, q, S, C; 9 int belong[MAXN], st[MAXN], ed[MAXN]; 10 LL a[MAXN], b[MAXN], add[MAXN]; 11 12 inline LL read() 13 { 14 LL x = 0, f = 1; 15 char ch = getchar(); 16 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 17 for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; 18 return x * f; 19 } 20 21 inline int find(int x, int y, int z) 22 { 23 int mid; 24 while(x < y) 25 { 26 mid = (x + y) >> 1; 27 if(b[mid] >= z) y = mid; 28 else x = mid + 1; 29 } 30 return x; 31 } 32 33 inline void retreat(int x, int y) 34 { 35 int i; 36 for(i = x; i <= y; i++) b[i] = a[i]; 37 std::sort(b + x, b + y + 1); 38 } 39 40 inline void init() 41 { 42 int i, j; 43 S = int(sqrt(n)) + 10; 44 for(i = 1; i <= n; i++) scanf("%d", &a[i]); 45 for(i = 1; i <= n; i += S) 46 { 47 st[++C] = i; 48 ed[C] = std::min(i + S - 1, n); 49 } 50 for(i = 1; i <= C; i++) 51 for(j = st[i]; j <= ed[i]; j++) 52 belong[j] = i; 53 for(i = 1; i <= C; i++) retreat(st[i], ed[i]); 54 } 55 56 inline void update(int x, int y, LL z) 57 { 58 int i, l = belong[x], r = belong[y]; 59 if(l == r) 60 { 61 for(i = x; i <= y; i++) a[i] += z; 62 retreat(st[l], ed[r]); 63 } 64 else 65 { 66 for(i = x; i <= ed[l]; i++) a[i] += z; 67 for(i = l + 1; i <= r - 1; i++) add[i] += z; 68 for(i = st[r]; i <= y; i++) a[i] += z; 69 retreat(st[l], ed[l]); 70 retreat(st[r], ed[r]); 71 } 72 } 73 74 inline int query(int x, int y, LL z) 75 { 76 int i, l = belong[x], r = belong[y], ans = 0; 77 if(l == r) return y + 1 - find(x, y + 1, z - add[l]); 78 ans += ed[l] - find(x, ed[l] + 1, z - add[l]) + 1; 79 for(i = l + 1; i <= r - 1; i++) ans += ed[i] - find(st[i], ed[i] + 1, z - add[i]) + 1; 80 ans += y - find(st[r], y + 1, z - add[r]) + 1; 81 return ans; 82 } 83 84 int main() 85 { 86 int i, j, x, y; 87 LL z; 88 char ch; 89 n = read(); 90 q = read(); 91 init(); 92 for(i = 1; i <= q; i++) 93 { 94 while ((ch=getchar()) < 'A' || ch > 'Z'); 95 x = read(); 96 y = read(); 97 z = read(); 98 if(ch == 'M') update(x, y, z); 99 else printf("%d\n", query(x, y, z)); 100 } 101 return 0; 102 }
View Code
转载于:https://www.cnblogs.com/zhenghaotian/p/6823527.html
[luoguP2801] 教主的魔法(二分 + 分块)相关推荐
- BZOJ3343 教主的魔法 二分法+分块
题意:给定一个数列,维护:1.[L,R]之间所有的数+=W 2.求[L,R]中大于等于C的数的数量 题解:更新用add标记,头尾俩块暴力重构:查询将每个块排序然后二分找. #include < ...
- Bzoj 3343: 教主的魔法(分块+二分答案)
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MB Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息 ...
- BZOJ——3343: 教主的魔法 || 洛谷—— P2801 教主的魔法
http://www.lydsy.com/JudgeOnline/problem.php?id=3343 || https://www.luogu.org/problem/show?pid=280 ...
- luogu P2801 教主的魔法
luogu P2801 教主的魔法 谜之分块 初学分块,找题练练手 大概分块示意图: 分块大法好! std: #include<bits/stdc++.h> using namespace ...
- 【bzoj3343】教主的魔法 (分块 + 二分)
传送门(权限题) 题目分析 题意为:给定一个数列,修改和查询两种操作,修改每次给定一个区间,区间的所有元素都加上一个给定值,查询询问一段区间的数权值大于等于给定值的数有多少个. 首先对原序列分块,然后 ...
- P2801-教主的魔法【分块,二分】
正题 题目链接:https://www.luogu.com.cn/problem/P2801 题目大意 nnn个数字,要求支持 区间加上一个数字www 询问一个区间内不小于www的数的个数 解题思路 ...
- P2801 教主的魔法(分块入门)
两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹 #include<bits/stdc++.h> using namespace std; const int m ...
- 洛谷-P2801 教主的魔法 分块
题目 题目链接 题意 修改:将一个区间内所有的数+C. 查询:查询一个区间内>C的数字有多少个. 题解 很经典的分快算法题目. 将数列分块以后,对块内的元素进行排序. 当我们要做修改操作的时候: ...
- bzoj 3343 教主的魔法 分块
修改直接对整块打标记,两边暴力. 查询需要保证每个整块有序,所以在修改时排序就好啦 #include<cstdio> #include<cstring> #include< ...
最新文章
- Android系统移植与调试之-------如何修改Android设备添加重启、飞行模式、静音模式等功能(一)...
- 百度ERNIE登顶GLUE榜单,得分首破90大关
- 李飞飞、吴恩达、Bengio等人的15大顶级深度学习课程,你收集全了吗?
- cgroups是什么
- Hadoop集群部署模型纵览1
- 【完结】林轩田机器学习技法终章
- 9大训练营免费开营!阿里云大数据团队的独门绝学全在这了
- jzoj4616-[NOI2016模拟7.12]二进制的世界【平衡规划,dp】
- linux v4l2 python,v4l2 Python - 流视频 - 映射缓冲区
- 微课|中学生可以这样学Python(2.2.4节):逻辑运算符
- 学python后到底能干什么-学会Python后都能做什么?网友们的回答简直不要太厉害...
- Hibernate异常归总
- java语言就业方向_Java的就业方向有哪些?
- python3手动配置环境变量
- python罗马数字转换阿拉伯数字_Python将阿拉伯数字转换为罗马数字的方法
- 芯片短缺并没有妨碍英特尔创下“有史以来业绩最好的一年”
- hadoop--HDFS基础(适合初学者)
- MODIFY和UPDATE
- 求知讲堂python+人工智能day8
- vue 生成二维码 并 可以下载带有边框背景颜色的二维码
热门文章
- java 饥饿现象,Java单例模式、饥饿模式代码实例
- easyui数据表格重置_数据库三种删除方式
- win10改成ubundu主题_如何将ubuntu引导win10,修改为win10引导ubuntu
- 操作系统上机作业-- 使用信号量解决生产者、计算者、消费者问题(多线程)
- Jmeter BeanShell学习(一) - BeanShell取样器(一)
- 《MySQL 8.0.22执行器源码分析(3.1)关于RowIterator》
- 求一个序列中最大的子序列_最大的斐波那契子序列
- 二进制文件签名_二进制数的签名表示
- Java ObjectInputStream readLong()方法(带示例)
- Java File类void deleteOnExit()方法(带示例)