传送门

以为对于这类问题线段树都能解决,分块比线段树菜,结果培训完才知道线段树是一种特殊的分块方法,有的分块的题线段树不能做,看来分块还是有必要学的。

对于这个题,先分块,然后另开一个数组对于每个块内排序。

区间加的话,加一个标记,每一个整块区间加,里面的数的相对大小不变,而左右两边零散的块直接暴力重构。

查询可以对于每个块二分查找。

时间复杂度应该是 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] 教主的魔法(二分 + 分块)相关推荐

  1. BZOJ3343 教主的魔法 二分法+分块

    题意:给定一个数列,维护:1.[L,R]之间所有的数+=W  2.求[L,R]中大于等于C的数的数量 题解:更新用add标记,头尾俩块暴力重构:查询将每个块排序然后二分找. #include < ...

  2. Bzoj 3343: 教主的魔法(分块+二分答案)

    3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MB Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息 ...

  3. BZOJ——3343: 教主的魔法 || 洛谷—— P2801 教主的魔法

    http://www.lydsy.com/JudgeOnline/problem.php?id=3343  ||  https://www.luogu.org/problem/show?pid=280 ...

  4. luogu P2801 教主的魔法

    luogu P2801 教主的魔法 谜之分块 初学分块,找题练练手 大概分块示意图: 分块大法好! std: #include<bits/stdc++.h> using namespace ...

  5. 【bzoj3343】教主的魔法 (分块 + 二分)

    传送门(权限题) 题目分析 题意为:给定一个数列,修改和查询两种操作,修改每次给定一个区间,区间的所有元素都加上一个给定值,查询询问一段区间的数权值大于等于给定值的数有多少个. 首先对原序列分块,然后 ...

  6. P2801-教主的魔法【分块,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/P2801 题目大意 nnn个数字,要求支持 区间加上一个数字www 询问一个区间内不小于www的数的个数 解题思路 ...

  7. P2801 教主的魔法(分块入门)

    两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹 #include<bits/stdc++.h> using namespace std; const int m ...

  8. 洛谷-P2801 教主的魔法 分块

    题目 题目链接 题意 修改:将一个区间内所有的数+C. 查询:查询一个区间内>C的数字有多少个. 题解 很经典的分快算法题目. 将数列分块以后,对块内的元素进行排序. 当我们要做修改操作的时候: ...

  9. bzoj 3343 教主的魔法 分块

    修改直接对整块打标记,两边暴力. 查询需要保证每个整块有序,所以在修改时排序就好啦 #include<cstdio> #include<cstring> #include< ...

最新文章

  1. 有了这篇 Shell 脚本实践指南,同事对我“刮目相看”!
  2. 一种用于360度全景视频超分的单帧多帧联合网络
  3. ceph学习笔记之七 数据平衡
  4. mysql悲观锁只用于读取吗_MySQL中悲观锁和乐观锁到底是什么?
  5. 产品问答 | PM最应该花时间做这件事……
  6. B. Complete the Word (尺取法)
  7. NRedis-Proxy - 高性能中间件服务器
  8. linux读取内存文件,linux – 使用模块读取内核内存
  9. iphone分屏功能怎么用_iPhone上10个隐藏小技巧,怎么用怎么爽
  10. 二维码原来可以这样玩
  11. 4个空格 tab vetur_python学习的10个小技巧
  12. linux getline函数用法,get()与getline()
  13. spark学习-32-SparkEnv的构造步骤
  14. qdir 自动创建多级目录_QDir 类 - 目录信息类
  15. 单龙芯3A3000-7A1000PMON研究学习-(7)撸起袖子干-make cfg 所执行的操作(d)
  16. Intellij IDEA之Mybatis插件:Free Mybatis Plugin
  17. 做了一个电驴 p2p资源搜索小软件
  18. C语言运算符优先级列表(超详细)
  19. 浙江大学精品课程视频合集
  20. 高频信号发生器设计—电感三点式振荡电路

热门文章

  1. c语言网上找程序组合,C语言程序我同学说在网上下的一章一章的小说组合成一个太麻烦,于是 爱问知识人...
  2. php异步请求$.post,如何用PHP实现异步请求、忽略返回值
  3. minio 并发数_c#(asp.net)线程配置总结
  4. python安装pyecharts清华_基于Python安装pyecharts所遇的问题及解决方法
  5. MySQL 后from多个表_MYSQL回顾(多表查询相关)
  6. java timezone id_java.util.TimeZone.setID()方法实例
  7. XADD和NEG命令
  8. BX、DI、SI、BP总结
  9. phpstud如何安装mysql新版_MySQL_图解MySQL数据库的安装和操作,一、MySQL下载与安装 1、 - phpStudy...
  10. python 课程设计 夏敏捷_Python课程设计(微课视频版21世纪高等学校通识教育规划教材)/计算机技术入门丛书...