分块学习小结1
来源:互联网 发布:暖暖环游世界人工智能 编辑:程序博客网 时间:2024/06/16 20:33
对于分块学习,主要是因为今天有位大牛Tom栋爷在讲根号级别复杂度的算法时,就是以分块来作为基础讲的,然而因为当时我并不懂分块,所以在听讲是一脸懵逼。晚上赶紧恶补一番,入了门,刷了道题。
进入正题
分块,就是将一段信息(数据结构,序列)分成几块处理,当然最基础的是序列上的分块,再高层点的就是树上的分块,分块套分块,分块套数据结构以及数据结构套分块。
因为我是初学者,今天就记录下最基础的分块中的最基础的部分,好让自己以后忘了可以看看自己的博客。
用题目来记录是最有效的
给一个长度为n的序列,每次会给其一段区间增加一个值,然后单点查询。
解法一:线段树,区间修改与单点查询,时间复杂度:每次查询修改
解法二:树状数组,经典的改段求点,时间复杂度为每次查询修改
当然了今天的重点应该是用分块来解决。
分块解法
我们将这长度为n的序列每m个分成一块,那么就有n/m个块,以及会多出不超过m个单位的数。
在区间修改时,先把这段区间内的每个块修改,用线段树的标记思想,打下标记,然后多出的那些不完整的部分直接暴力修改权值。
时间复杂度是:修改块
运用一些数学知识(均值不等式),当m为
分块:
block=sqrt(n); //每一个块的个数。 fo(i,1,n) bl[i]=(i-1)/block+1; //bl数组表示第i个位置属于的块是哪个 bl[0]=1; bl[n+1]=bl[n]; //我会处理边界 fo(i,1,n){ int x,y; scanf("%d%d",&x,&y); add(x,y); //区间修改 } fo(i,1,n-1) printf("%d ",a[i]+lab[bl[i]]); //答案是本身的值加块上的标记的值 printf("%d\n",a[n]+lab[bl[n]]);//这是在交题时的格式问题,直接忽略就是了
区间修改:
void add(int a,int b,int c){ bool bz1,bz2;//我比较弱,用bz1,bz2来记录x,y是否是处于各自块的边界 if (bl[a-1]==bl[a]) bz1=false; else bz1=true; if (bl[b+1]==bl[b]) bz2=false; else bz2=true; if (bl[a]==bl[b]){ if (bz1 && bz2) lab[bl[a]]+=c;//lab表示第i个块当前的修改标记 else fo(i,a,b) v[i]+=c; } else { if (bz1 && bz2) fo(i,bl[a],bl[b]) lab[i]+=c; else if (bz1 && !bz2) { fo(i,bl[a],bl[b]-1) lab[i]+=c;//整块打下标记 fo(i,(bl[b]-1)*block+1,b) v[i]+=c;//多余部分直接暴力修改 } else if (!bz1 && bz2) { fo(i,bl[a]+1,bl[b]) lab[i]+=c; fo(i,a,bl[a]*block) v[i]+=c; } else { fo(i,bl[a]+1,bl[b]-1) lab[i]+=c; fo(i,a,bl[a]*block) v[i]+=c; fo(i,(bl[b]-1)*block+1,b) v[i]+=c; } }}
实题:hdu1556
题意很明显,就不多说了。
这道题是可以由上述方法解决,涉及到区间修改与单点查询,套上模板即可。
代码:
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int maxn=1e5+5;int bl[maxn],a[maxn],lab[350],n,block;void add(int x,int y){ bool bz1,bz2; if (bl[x]==bl[x-1]) bz1=false; else bz1=true; if (bl[y]==bl[y+1]) bz2=false; else bz2=true; if (bl[x]==bl[y]){ if (bz1 && bz2) ++lab[bl[x]]; else fo(i,x,y) ++a[i]; } else { if (bz1 && bz2) fo(i,bl[x],bl[y]) ++lab[i]; else if (bz1 && !bz2) { fo(i,bl[x],bl[y]-1) lab[i]++; fo(i,(bl[y]-1)*block+1,y) ++a[i]; } else if (!bz1 && bz2) { fo(i,bl[x]+1,bl[y]) lab[i]++; fo(i,x,bl[x]*block) ++a[i]; } else { fo(i,bl[x]+1,bl[y]-1) lab[i]++; fo(i,x,bl[x]*block) ++a[i]; fo(i,(bl[y]-1)*block+1,y) ++a[i]; } }}int main(){ scanf("%d",&n); while (n){ block=sqrt(n); fo(i,1,n) bl[i]=(i-1)/block+1; bl[0]=1; bl[n+1]=bl[n]; fo(i,1,n){ int x,y; scanf("%d%d",&x,&y); add(x,y); } fo(i,1,n-1) printf("%d ",a[i]+lab[bl[i]]);//差点被格式坑死- -||| printf("%d\n",a[n]+lab[bl[n]]); fo(i,1,n+1){ bl[i]=0; a[i]=0; } scanf("%d",&n); memset(lab,0,sizeof(lab)); } }
分块还有很多需要学习,今天只是学习了一点,下次接着学习。
0 0
- 分块学习小结1
- 分块学习小结2
- 分块学习笔记
- 分块算法学习记录
- 分块学习记录
- 树上 分块 莫队 题型小结 加 题集
- 学习小结1
- php学习小结1
- oracle 学习小结1
- cmmi学习小结1
- Hadoop 学习小结(1)
- jquery 小结学习1
- ejb3 学习小结1
- oracle 学习小结1
- jquery学习小结1
- ror学习小结1
- python学习小结1
- 阶段学习小结1
- android异常捕获,上线前的操作
- Hibernate 的配置
- 归并排序
- C++:Boost库智能指针_shared_array
- 矩阵形式回归系数W推导
- 分块学习小结1
- tomcat 字符集设置 url中文乱码解决大全
- [FZU 2142 Center of a Tree] 树形DP
- 看完了第二遍C++Primer,学习心得与问题
- 【图像识别】利用BP神经网络做特征向量分类
- POJ 3259 Wormholes(spfa算法判断负权环)
- USB转TTL、USB转232的区别
- BZOJ 1012: [JSOI2008]最大数maxnumber
- PuzzleGame-问题笔记(第一篇+感悟)