今天接着昨天的继续讲数据结构

今天先是 分块

在统计问题中,尤其是序列问题,经常涉及到区间的操作,比如修改一段区间的元素,询问某个区间的元素的信息。

如果每次都对一整个区间的每一个元素进行操作的话,那可能就很笨重,所以怎么快速地统计某一段区间的信息就成为了问题所在。

我们考虑把整个序列分成若干个区间,每一个区间称为一个“块”,这样,修改或者询问的每一个区间都能被表示为若干个连续的整块和若干个单个元素的拼接。

对于连续的整块,我们直接询问或者修改这个整块的信息即可,对于单个的元素我们暴力遍历一遍。

如果我们设块的大小为S,块的个数为C的话,那么显然S*C≈N,并且一个区间会被分为不超过C个整块和不超过2S个单个元素,显然,取S=C=n^0.5最优。

分块的思想并不仅仅适用于序列,它实质上用到了一种均衡的思想。

分块算法是一种很常见的根号算法,一般它的时间复杂度会带根号。

分块和线段树的区别在于,分块算法可以维护一些线段树维护不了的东西,例如单调队列等,线段树能维护的东西必须能够进行信息合并,而分块则不需要。

不过,它们也有共同点,分块和线段树一样,分块需要支持类似标记合并的东西。

简单来说,分块算法就是优化过后的暴力。

至于代码...大概是这个样子...(嗯我不会告诉你我直接粘贴的mzx的资源)

  1. Block{
  2. int n,a[MAXN],belong[MAXN];
  3. int S,C,st[MAXN],ed[MAXN],sum[MAXN],delta[MAXN];
  4.  
  5. void pretreat(){
  6. S=int(sqrt(double(n)));
  7. for(int i=;i<=n;i+=S){
  8. st[++C]=i;
  9. ed[C]=min(i+S-,n);
  10. }
  11. for(int i=;i<=C;i++)
  12. for(int j=st[i];j<=ed[i];j++)
  13. belong[j]=i,sum[j]+=a[i];
  14. }
  15.  
  16. int update(int x,int k){
  17. a[x]+=k;
  18. sum[belong[x]]+=k;
  19. }
  20.  
  21. int query(int x,int y){
  22. int l=belong[x],r=belong[y],ans=;
  23. if(l==r){
  24. for(int i=x;i<=y;i++)
  25. ans+=a[i]+delta[belong[i]];
  26. }
  27. else{
  28. for(int i=x;i<=ed[l];i++)
  29. ans+=a[i]+delta[belong[i]];
  30. for(int i=l+;i<r;i++)
  31. ans+=sum[i]+delta[i]*(ed[i]-st[i]+);
  32. for(int i=st[r];i<=y;i++)
  33. ans+=a[i]+delta[belong[i]];
  34. }
  35. return ans;
  36. }
  37.  
  38. }

至于线段树...本博客里面已经写过一篇了,这里不再细说。

链接:http://www.cnblogs.com/MisakaAzusa/p/8485726.html

那么摘抄一下mxz ppt里面对线段树的解释

线段树是一种较为高级的数据结构,它用来维护区间的信息,我把它理解为更高级的一种分块方式:

根节点代表一整个区间[1,n],然后把它从中间等分为两个区间,作为它的两个儿子,然后再将这两个区间等分……如此递归下去,我们就构造出了一棵线段树。

线段树有多少个结点呢?

第1层有1个,第2层有2个,第3层有4个……第i层有2^(i-1)个。 但是最多只有O(logn)层,所以实际上节点数大约是2n个。

单点修改:

以维护最大值为例,我们在每个结点存储这个结点所对应的区间中所有元素的最大值,怎么初始化呢?

很简单,每个叶子结点都是一个长度为1的区间,对着序列直接DFS建树,叶子节点的值能直接确定,而一个非叶子结点的区间最大值就是它的两个儿子的最大值取更大那个,因为每个结点所对

应的区间都刚好是它另个儿子所对应的区间的合并。

于是,如果我们要修改某一个点的值,那么直接dfs到它所对应的那个叶子结点,在回溯的过程中更新包含这个点的区间即可,这些结点就是从根到这个叶子结点的一条链。

区间查询:

如果我们要询问一个区间,该怎么办?

回想一下分块的处理方法,一个区间能被划分为若干个整块和若干个点。

但是在线段树中,“点”也是一个块。 所以在询问区间时,我们直接对线段树进行DFS,如果一个结点所对应的区间被询问的区间完全覆盖了,那就把它的信息统计上并且不再往下搜索。

与线段树类似的,还有树状数组

树状数组(BIT)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下
进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。

这里拿luogu P3374 树状数组模板为例

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. int n,m;
  6. int tree[],a[];
  7. int lowbit(int x)
  8. {
  9. return x&-x;
  10. }
  11. void add(int k,int num)//给k位置的数值加num
  12. {
  13. while(k<=n)
  14. {
  15. tree[k]+=num;
  16. k+=lowbit(k);
  17. }
  18. }
  19. int sum(int k)//前缀和
  20. {
  21. int s=;
  22. while(k)
  23. {
  24. s+=tree[k];
  25. k-=lowbit(k);
  26. }
  27. return s;
  28. }
  29. int main()
  30. {
  31. scanf("%d%d",&n,&m);
  32. for(int i=;i<=n;i++)
  33. {
  34. scanf("%d",&a[i]);
  35. add(i,a[i]);
  36. }
  37. for(int i=;i<=m;i++)
  38. {
  39. int c;scanf("%d",&c);
  40. if(c == )
  41. {
  42. int x,k;
  43. scanf("%d%d",&x,&k);
  44. add(x,k);
  45. }
  46. else
  47. {
  48. int x,y;scanf("%d%d",&x,&y);
  49. printf("%d\n",sum(y)-sum(x-));
  50. }
  51. }
  52. return ;
  53. }

学大伟业 Day 6 培训总结的更多相关文章

  1. 学大伟业 Day 1 培训总结

    第一天培训,讲的基本算法,东西很多.还有些数论,图论,数据结构and some small tricks 一.输入输出技巧 //输入输出技巧 /* scanf.printf:速度快,需要记忆不同数据类 ...

  2. 学大伟业 Day 5 培训总结

    今天讲数据结构 先从mzx大佬的ppt摘抄一段: 数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合. 通常情况下,精心选择的数据结构可以带来更高的运行或 ...

  3. 学大伟业 Day 3 培训总结

    今天讲的字符串: 不多说,直接看题 一.表达式求值 题目大意: 输入一行一个表达式,计算其答案 表达式包含非负整数.加减乘除.括号 两种做法 ·栈 ·表达式树 这里更推荐表达式树,因为栈是先压进去,逆 ...

  4. 学大伟业 Day 2 培训总结

    一.dp 动态规划的本质 是一种思想.通过对原问题划分成子问题,寻找子问题之间的联系,通过求解子问题得出原问题的解.与贪心不同的是,动归是深谋远虑,考虑全局最优解:而贪心则目光短浅,只考虑局部最优解. ...

  5. 学大伟业 Day 4 培训总结

    今天讲的全是dp... 不多废话,先看一道经典的模板LIS(最长不下降子序列) 一.LIS 给定一个长度为N的数列,求最长上升子序列 例:1 7 2 8 3 4 答案:1 2 3 4 代码: #inc ...

  6. 学大伟业Day1解题报告

    学大伟业Day1解题报告 张炳琪 一.   时间分配 T1:30分钟  T2: 60分钟  T3:100分钟 二.答题情况及错因 T1:100         T2:55             T3 ...

  7. 学大伟业 2017 国庆 Day1

    期望得分:100+100+20=220 实际得分:100+100+20=220 (好久没有期望==实际了 ,~\(≧▽≦)/~) 对于 a........a 如果 第1个a 后面出现的第1个b~z 是 ...

  8. 2017-10-23学大伟业Day1

    T1 叉叉 题目名称 叉叉 程序文件名 cross 输入文件名 cross.in 输出文件名 cross.out 每个测试点时限 1秒 内存限制 128MB 测试点数目 10 每个测试点分值 10 是 ...

  9. 学大伟业 国庆Day2

    期望得分:30+100+0=130 实际得分:30+100+20=150 忍者钩爪 (ninja.pas/c/cpp) [问题描述] 小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个 ...

随机推荐

  1. android应用签名详解

    1.Eclipse工程中右键工程,弹出选项中选择 android工具-生成签名应用包: 2.选择需要打包的android项目工程: 3.如果已有私钥文件,选择私钥文件 输入密码,如果没有私钥文件见 第 ...

  2. Unity3D游戏轻量级xlua热修复框架

    Unity3D游戏轻量级xlua热修复框架   一 这是什么东西 前阵子刚刚集成xlua到项目,目的只有一个:对线上游戏C#逻辑有Bug的地方执行修复,通过考察xlua和tolua,最终选择了xlua ...

  3. ArcGIS发布地图服务后直接调用查看方法

    做项目配置了一个地理底图,不知道有没有问题,如何给到客户查看并确认呢? 首先在ArcGIS上发布该地图: 打开地图后->文件->共享为->服务…… 发布成功后,得到可以访问的地图服务 ...

  4. 支付宝小程序与微信小程序开发功能和语法糖不同

    最近开始负责公司webapp数据打通支付宝小程序,之前已经打通了微信小程序,现在根据支付宝小程序的开发文档在之前的模板上面做修改. 在修改模板的过程中,总结一下双方功能和语法糖的不同之处. 框架: a ...

  5. js中防止事件传播的方法

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. C++程序设计基础(8)main函数

    注:读<程序员面试笔记>笔记总结 1.知识点 (2)main函数的形式 //first type int main() //second type int main(int argc,ch ...

  7. win10的xbox下载应用或者游戏时,出现0x80070422和0x80073D0A的解决办法

    这个错误:0x80070422是因为关闭了windows update这个服务导致的 这个错误:0x80073D0A是因为关闭了windows firewall这个服务导致的 具体操作: cmd下se ...

  8. Node.js之Buffer

    JavaScript 语言自身只有字符串数据类型,没有二进制数据类型.但在处理像TCP流或文件流时,必须使用到二进制数据.因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存 ...

  9. 2018-12-20 第二章Java 预习作业

    一.什么是变量?如何使用变量? 答:变量是在程序运行中其值可以改变的量,它是Java程序的一个基本存储单元. 变量的语法格式如下: [访问修饰符]变量类型 变量名[=初始值]: 二.java中基本数据 ...

  10. Java使用UDP聊天程序

    主要想测试Java UDP通信.Java UDP使用DatagramSocket和DatagramPacket完成UDP通信 主要思路: 1.本机通信,ip地址为:127.0.0.1 2.开一个线程监 ...