学大伟业 Day 6 培训总结
今天接着昨天的继续讲数据结构
今天先是 分块
在统计问题中,尤其是序列问题,经常涉及到区间的操作,比如修改一段区间的元素,询问某个区间的元素的信息。
如果每次都对一整个区间的每一个元素进行操作的话,那可能就很笨重,所以怎么快速地统计某一段区间的信息就成为了问题所在。
我们考虑把整个序列分成若干个区间,每一个区间称为一个“块”,这样,修改或者询问的每一个区间都能被表示为若干个连续的整块和若干个单个元素的拼接。
对于连续的整块,我们直接询问或者修改这个整块的信息即可,对于单个的元素我们暴力遍历一遍。
如果我们设块的大小为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,如果一个结点所对应的区间被询问的区间完全覆盖了,那就把它的信息统计上并且不再往下搜索。
与线段树类似的,还有树状数组:
这里拿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 培训总结的更多相关文章
- 学大伟业 Day 1 培训总结
第一天培训,讲的基本算法,东西很多.还有些数论,图论,数据结构and some small tricks 一.输入输出技巧 //输入输出技巧 /* scanf.printf:速度快,需要记忆不同数据类 ...
- 学大伟业 Day 5 培训总结
今天讲数据结构 先从mzx大佬的ppt摘抄一段: 数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合. 通常情况下,精心选择的数据结构可以带来更高的运行或 ...
- 学大伟业 Day 3 培训总结
今天讲的字符串: 不多说,直接看题 一.表达式求值 题目大意: 输入一行一个表达式,计算其答案 表达式包含非负整数.加减乘除.括号 两种做法 ·栈 ·表达式树 这里更推荐表达式树,因为栈是先压进去,逆 ...
- 学大伟业 Day 2 培训总结
一.dp 动态规划的本质 是一种思想.通过对原问题划分成子问题,寻找子问题之间的联系,通过求解子问题得出原问题的解.与贪心不同的是,动归是深谋远虑,考虑全局最优解:而贪心则目光短浅,只考虑局部最优解. ...
- 学大伟业 Day 4 培训总结
今天讲的全是dp... 不多废话,先看一道经典的模板LIS(最长不下降子序列) 一.LIS 给定一个长度为N的数列,求最长上升子序列 例:1 7 2 8 3 4 答案:1 2 3 4 代码: #inc ...
- 学大伟业Day1解题报告
学大伟业Day1解题报告 张炳琪 一. 时间分配 T1:30分钟 T2: 60分钟 T3:100分钟 二.答题情况及错因 T1:100 T2:55 T3 ...
- 学大伟业 2017 国庆 Day1
期望得分:100+100+20=220 实际得分:100+100+20=220 (好久没有期望==实际了 ,~\(≧▽≦)/~) 对于 a........a 如果 第1个a 后面出现的第1个b~z 是 ...
- 2017-10-23学大伟业Day1
T1 叉叉 题目名称 叉叉 程序文件名 cross 输入文件名 cross.in 输出文件名 cross.out 每个测试点时限 1秒 内存限制 128MB 测试点数目 10 每个测试点分值 10 是 ...
- 学大伟业 国庆Day2
期望得分:30+100+0=130 实际得分:30+100+20=150 忍者钩爪 (ninja.pas/c/cpp) [问题描述] 小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个 ...
随机推荐
- 第十三章:基于socket.io实现即时通信
安装好环境,请参考ionic环境搭建之windows篇 和 ionic环境搭建之OS X篇 . 服务器端的搭建参考socket io官网,里面有非常详细的描述,按照步骤下来,最终可以在localhos ...
- TOJ 2857 Stockbroker Grapevine
描述 Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of s ...
- jqgrid 上移下移单元格
在表格中常常需要调整表格中数据的显示顺序,我用的是jqgrid,实现原理就是将表中的行数保存到数据库中,取数据时按行进行排序 1.上移,下移按钮 <a href="javascript ...
- C# 定制特性
一.初识特性 特性(attribute)是被指定给某一声明的一则附加的声明性信息. 设计类型的时候可以使用各种成员来描述该类型的信息,但有时候我们可能不太愿意将一些附加信息放到类的内部,因为这样,可能 ...
- (一)安装Python
一.安装python 打开 Python官网,找到“Download”, 在其下拉菜单中选择自己的平台(Windows/Mac),一般的Linux平台已经自带的Python,所以不需要安装,通过打开“ ...
- WPF的项目,ListBox 纵向滚动条不显示
最近在做WPF的项目,ListBox 纵向滚动条不显示,但是鼠标滚轮可以在ListBox中使用,但是必须要出现纵向滚动条. 索性就直接在listBox外面包裹一个ScrollViewer. Scro ...
- Java Web基础——Action+Service +Dao三层的功能划分 (转载)
原文:https://blog.csdn.net/inter_peng/article/details/41021727 仅供自己学习使用: 1. Action/Service/DAO简介: Acti ...
- linux环境下安装jdk(本文示例是jdk1.6.0_45)
第一步:创建一个文件夹安装jdk(虽说地址一般自定义,但是为了方便查找请按照笔者建议目录 ):/usr/java 将jdk-6u45-linux-x64.bin文件放到 /usr/java 文件夹 ...
- Shader之ShaderUI使用方法
shader中的宏定义在material中Inspector中打开 Shader "Custom/Redify" { Properties{ _MainTex("Base ...
- asyncio标准库2 Hello Clock
如何调度协程,并发运行 asyncio.gather方法可以聚合协程or future def gather(*coros_or_futures, loop=None, return_exceptio ...