【快速处理】分块算法

分块算法

----------------------------------------------------------

1.思想

如果我们需要对一个特定的序列进行操作,那么非常直观、简单的方法就是纯暴力(不,那叫模拟)。

不过如果暴力能过的话,那就呵呵了。

所以我们要想一些比较高能的数据结构——分块。

相比线段树来说,分块算法比较难实现,但是只要深入理解,就可以实现了,只不过需要一些数据结构的辅助。

分块实质来说就是把一个序列切分,从而实现对查询、查找、替换等等操作的高效处理。

----------------------------------------------------------

2.辅助结构

我们知道,数组的单点查询时间为O(1),而插入为O(n)

                链表的单点查询时间为O(n),而插入为O(1)

而在NOIP里,vector总体来说是比数组快的,所以我们可以用vector来储存每块,只不过如果让插入也这用vector的话,那么时间就不可理喻了。

插入的话,我们可以使用pair

通常要定义这两个数据结构,简单的话那个pair就不用了,这要根据题意定义。

----------------------------------------------------------

3.模版

操作:建块(rebuild)

注意:一开始不必要建块,但是要在过程中将序列分块

用途:当当前块太大时,可以使用此函数将一个大块分裂

void rebuild()
{
    top=0;
    for(int i=1;i<=m;i++)
    {
        for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++)
            st[++top]=*j;
        ve[i].clear();//清空当前块
    }
    int blo2=sqrt(top);
    for(int i=1;i<=top;i++)
        ve[(i-1)/blo2+1].push_back(st[i]);
    m=(top-1)/blo2+1;
}

  

操作:区间加法(add)

注意:blo是分块一个重要的变量,是N的开方,大家可以仔细想一想为什么

用途:在需要操作区间加法时可以使用

void add(int a,int b,int c)
{
    for(int i=a;i<=min(bl[a]*blo,b);i++)
        v[i]+=c,sum[bl[a]]+=c;;
    if(bl[a]!=bl[b])
        for(int i=(bl[b]-1)*blo+1;i<=b;i++)
            v[i]+=c,sum[bl[b]]+=c;
    for(int i=bl[a]+1;i<=bl[b]-1;i++)
        atag[i]+=c;
}

  

操作:插入

注意:自己可以控制块的大小

用途:插入元素

void insert(int a,int b)
{
    pair<int,int> t=query(a);
    ve[t.first].insert(ve[t.first].begin()+t.second,b);
    if(ve[t.first].size()>20*blo)//分裂大块
        rebuild();
}

常用的分块只有这几个操作,更多操作可见hzwer

时间: 2024-08-29 20:42:21

【快速处理】分块算法的相关文章

分块算法及模板

此文为博主原创,转载时请通知博主,并把原文链接放在正文醒目位置. 简要介绍 分块算法就是把一串数据分割成几块数据的算法,其实是对暴力的一种优化. 通常在分块时,每块的大小为√n.但最后一块的大小也可能小于√n,只能用暴力来算. 通过把对单个数据的操作转化为对几个块的数据的操作,能够节省时间,提高运算效率. 分块算法在处理大范围的修改.查询问题时有很大优势. 分块算法代码 1 /*此代码主要模仿了钟皓曦大佬的分块算法*/ 2 #include<iostream> 3 #include<cs

每日一小练——快速Fibonacci数算法

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:快速Fibonacci数算法 内容:先说说Fibonacci数列,它的定义是数列:f1,f2....fn有如下规律: 尝试寻找快速的求出fn的方法 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分钟就超神..奥,不对就解决了! 其实题目中就给出了这个算法的递归形式,所以首先我想到的是递归解法,不过因为求解快速方法在递归之前,我编写了一个非递归的算法 #include <iostream> usi

hdu 5057 Argestes and Sequence(分块算法)

Argestes and Sequence Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 566    Accepted Submission(s): 142 Problem Description Argestes has a lot of hobbies and likes solving query problems espec

位运算之——按位与(&amp;)操作——(快速取模算法)

由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快. 按位与(Bitwise AND),运算符号为& a&b 的操作的结果:a.b中对应位同时为1,则对应结果位也为1. 例如: 10010001101000101011001111000 & 111111100000000 --------------------------------------------- 10101100000000 对10101100000000进行右移8位得到的是101011,这就得

快速堆栈模糊算法

上一篇快速高斯模糊的原作者也有另一个比较快速的模糊算法Stack Blur,字面意思为堆栈模糊. 源地址为:http://incubator.quasimondo.com/processing/fast_blur_deluxe.php 这个算法在多个平台上都有实现,安卓以及IOS,JS等. processing源码:http://incubator.quasimondo.com/processing/stackblur.pde 效果图: 转为C语言实现版本. 代码如下: // Stack Blu

算法快速回顾——排序算法

常用排序算法有以下几种:冒泡排序.插入排序.快速排序.归并排序.堆排序. 本文将对五种常用算法分析并实现. //交换两个元素的值 这里列出几种不同写法 void swap(int *a, int *b) { int c = *a; *a = *b; *b = c; } void swap(int *a,int *b) { *a = (*a)^(*b); *b = (*b)^(*a); *a = (*a)^(*b); } void swap(int *a,int *b) { *a = *a + *

快速傅立叶变换算法FFT——图像处理中的数学原理详解22

欢迎关注我的博客专栏"图像处理中的数学原理详解" 全文目录请见 图像处理中的数学原理详解(总纲) http://blog.csdn.net/baimafujinji/article/details/48467225 图像处理中的数学原理详解(已发布的部分链接整理) http://blog.csdn.net/baimafujinji/article/details/48751037 交流学习可加图像处理研究学习QQ群(529549320) 傅立叶变换以高等数学(微积分)中的傅立叶级数为基

非递归快速求幂算法

快速求正整数次幂,当然不能直接死乘.举个例子:3 ^ 999 = 3 * 3 * 3 * … * 3直接乘要做998次乘法.但事实上可以这样做,先求出2^k次幂:3 ^ 2 = 3 * 33 ^ 4 = (3 ^ 2) * (3 ^ 2)3 ^ 8 = (3 ^ 4) * (3 ^ 4)3 ^ 16 = (3 ^ 8) * (3 ^ 8)3 ^ 32 = (3 ^ 16) * (3 ^ 16)3 ^ 64 = (3 ^ 32) * (3 ^ 32)3 ^ 128 = (3 ^ 64) * (3

刷题总结——分块算法(bzoj2821作诗)

题目: Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一 些汉字构成诗.因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次.而且SHY认 为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!).于是SHY请LYD安排选 法.LYD这