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

今天先是 分块

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

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

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

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

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

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

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

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

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

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

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

 Block{
int n,a[MAXN],belong[MAXN];
int S,C,st[MAXN],ed[MAXN],sum[MAXN],delta[MAXN]; void pretreat(){
S=int(sqrt(double(n)));
for(int i=;i<=n;i+=S){
st[++C]=i;
ed[C]=min(i+S-,n);
}
for(int i=;i<=C;i++)
for(int j=st[i];j<=ed[i];j++)
belong[j]=i,sum[j]+=a[i];
} int update(int x,int k){
a[x]+=k;
sum[belong[x]]+=k;
} int query(int x,int y){
int l=belong[x],r=belong[y],ans=;
if(l==r){
for(int i=x;i<=y;i++)
ans+=a[i]+delta[belong[i]];
}
else{
for(int i=x;i<=ed[l];i++)
ans+=a[i]+delta[belong[i]];
for(int i=l+;i<r;i++)
ans+=sum[i]+delta[i]*(ed[i]-st[i]+);
for(int i=st[r];i<=y;i++)
ans+=a[i]+delta[belong[i]];
}
return ans;
} }

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

链接: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 树状数组模板为例

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int tree[],a[];
int lowbit(int x)
{
return x&-x;
}
void add(int k,int num)//给k位置的数值加num
{
while(k<=n)
{
tree[k]+=num;
k+=lowbit(k);
}
}
int sum(int k)//前缀和
{
int s=;
while(k)
{
s+=tree[k];
k-=lowbit(k);
}
return s;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
}
for(int i=;i<=m;i++)
{
int c;scanf("%d",&c);
if(c == )
{
int x,k;
scanf("%d%d",&x,&k);
add(x,k);
}
else
{
int x,y;scanf("%d%d",&x,&y);
printf("%d\n",sum(y)-sum(x-));
}
}
return ;
}

学大伟业 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. How to add more to Git Bash on Windows

    How to add more to Git Bash on Windows Download the lastest wget binary for windows from https://ete ...

  2. elasticSearch请求流程图

  3. pat1006. Sign In and Sign Out (25)

    1006. Sign In and Sign Out (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  4. JS实现多少小时前,多少天前...

    最近需要实现题目的功能,因为我的时间戳是PHP生成的,所以转换JS时间戳需要乘1000,废话不多说,看下面的代码把! 大家可以判断一下传进来的值是否为数值型,还有判断是否比当前的时间戳大!可以根据结果 ...

  5. bzoj 3576: [Hnoi2014]江南乐

    Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F ...

  6. 深入理解JavaScript系列(13):This? Yes,this!

    介绍 在这篇文章里,我们将讨论跟执行上下文直接相关的更多细节.讨论的主题就是this关键字.实践证明,这个主题很难,在不同执行上下文中this的确定经常会发生问题. 许多程序员习惯的认为,在程序语言中 ...

  7. vsCode代码缩略图

    vsCode配置代码缩略图: 文件--首选项--设置 搜索 minimap    true 打开 false 关闭

  8. 04.Dictionary字典键值对集合

    Dictionary字典键值对集合和Hashtable键值对集合的功能非常类似, 只是在声明的时候,必须为其制定值的类型. 示例代码: namespace _11.Dictionary字典集合的学习 ...

  9. 线程安全的Dictionary

    线程安全的DictionaryConcurrentDictionary<TKey, TValue> 类

  10. scp命令的使用

    scp命令是什么 scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令. scp命令用法 scp [-1246BCpqrv] [-c cipher ...