分块学习

分块是一种非常常用的技巧,他功能非常强大;然而相对的,它的时间复杂度较高,这也是它的缺陷。

设定每块大小为根号n,这样就把序列分为了n/根号n块

对于每一块,整体处理,不能构成一块的,暴力处理

代码:

    for(int i=1;i<=n;i++)
    {
        a[i]=read();belong[i]=(i-1)/t+1;
        sum[belong[i]]+=a[i];
    } 

这样就完成了分块 例如10个数,belong[i]分别为 1 1 1 2 2 2 3 3 3 4

修改或查询时分三段区间

1. L~min(belong[L],R),闭区间。

2. belong[L]+1~belong[R],半开半闭区间。

3.(belong[R]-1)*t+1~t,闭区间。

这样就OK啦 例如区间求和

代码:

int query(int x,int y)
{
    ans=0;
    for(int i=x;i<=min(y,belong[x]*t);i++) ans+=a[i];
    for(int i=belong[x]+1;i<belong[y];i++) ans+=sum[i];
    if(belong[x]!=belong[y]) for(int i=(belong[y]-1)*t+1;i<=y;i++) ans+=a[i];
    return ans;
}

以下3题练练手

T1 http://codevs.cn/problem/1080/ 线段树练习

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

#define N 100001

using namespace std;
int n,m,x,y,z,t,ans,a[N],belong[N],sum[N];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}

int query(int x,int y)
{
    ans=0;
    for(int i=x;i<=min(y,belong[x]*t);i++) ans+=a[i];
    for(int i=belong[x]+1;i<belong[y];i++) ans+=sum[i];
    if(belong[x]!=belong[y]) for(int i=(belong[y]-1)*t+1;i<=y;i++) ans+=a[i];
    return ans;
}

int main()
{
    n=read();t=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        belong[i]=(i-1)/t+1;
        sum[belong[i]]+=a[i];
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();z=read();
        if(x==1){a[y]+=z;sum[belong[y]]+=z;}
        if(x==2){printf("%d\n",query(y,z));}
    }
    return 0;
}

单点修改,区间查询

T2 http://codevs.cn/problem/1081/ 线段树练习2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

#define N 100001

using namespace std;
int n,m,q,x,y,z,t,ans,a[N],belong[N],tot[N];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}

int main()
{
    n=read();t=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        belong[i]=(i-1)/t+1;
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();
        if(x==1)
        {
            y=read();z=read();q=read();
            for(int i=y;i<=min(z,belong[y]*t);i++) a[i]+=q;
            for(int i=belong[y]+1;i<belong[z];i++) tot[i]+=q;
            if(belong[y]!=belong[z])for(int i=(belong[z]-1)*t+1;i<=z;i++) a[i]+=q;
        }
        if(x==2)
        {
            y=read();
            printf("%d\n",a[y]+tot[belong[y]]);
        }
    }
    return 0;
}

单点查询,区间修改

T3 http://codevs.cn/problem/1082/ 线段树练习3

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

#define N 200001

using namespace std;
long long n,m,x,y,z,t,w,R;
long long sum[N],flag[N],ans,a[N],belong[N];

inline long long read()
{
    int x=0,f=1;char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}

int main()
{
    n=read();t=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();belong[i]=(i-1)/t+1;
        sum[belong[i]]+=a[i];
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        w=read();
        if(w==1)
        {
            x=read();y=read();z=read();R=min(y,belong[x]*t);
            for(int i=x;i<=R;i++) a[i]+=z,sum[belong[i]]+=z;
            for(int i=belong[x]+1;i<belong[y];i++) flag[i]+=z;
            if(belong[x]!=belong[y])
            for(int i=(belong[y]-1)*t+1;i<=y;i++) a[i]+=z,sum[belong[i]]+=z;
        }
        else
        {
            ans=0;
            x=read();y=read();R=min(y,belong[x]*t);
            for(int i=x;i<=R;i++) ans+=a[i]+flag[belong[i]];
            for(int i=belong[x]+1;i<belong[y];i++) ans+=sum[i]+flag[i]*t;
            if(belong[x]!=belong[y])
            for(int i=(belong[y]-1)*t+1;i<=y;i++) ans+=a[i]+flag[belong[i]];
            printf("%lld\n",ans);
        }
    }
    return 0;
}

区间修改+区间查询

时间: 2024-08-25 05:05:42

分块学习的相关文章

分块学习笔记

最近在做学长模拟赛的时候发现分块可以的很多部分分,所以就跟着学了分块. 分块其实是一种做题的思路,由于我只是学了一下线性的分块,所以就光说一下线性的吧:其实大体思路就是当我们要对一个规模比较大的问题进行修改或查询的时候,用数据结构不好去维护,但是范围太大又不能用暴力去做,所以我们就可以把这个大的数据分成大约是sqrt(n),但是也不一定. 放一道例题:来自国家队的论文 由于是写论文的人自己出的题没所以没有数据,我就自己拍了一下,我觉得应该是A了,如果有谁拍出了错,记得跟我说一下.. #inclu

分块学习总结

分块,是一种可以说是,相当,暴力的数据结构.分块算法的思想是通过适当的划分,预处理一部分信息保存下来,用空间换取时间,达到时空平衡.基本操作是,将一段序列,分成一定数量的块,每一块有一个长度,表示一段区间.对于区间操作,通过对完整块的整体操作和对不完整块的暴力操作而使复杂度尽可能的低一般来讲,块的大小常设为sqrt(n),但实际上块的大小可以任意自定,不过肯定是要让复杂度尽可能的优秀分块的效率要低于树状数组和线段树,且代码实现比较随意,相对来说更好理解.但是俗话说的好:越简单的东西,就意味着它越

Mootools 学习随笔

简单的介绍下Mootools: MooTools是一个简洁,模块化,面向对象的开源JavaScript web应用框架.在处理js.css.html时候,为web开发者提供了一个跨浏览器的js解决方案. 优点: 1.灵活,模块化的框架,用户可以选择自己需要的组件. 2.MooTools符合OO的思想,使代码更强壮,有力,有效. 3.高效的组件机制,可以和flash进行完美的交互. 4.对于DOM的扩展增强,使开发者更好的利用document. 组件: 1.Core:常用函数集合,核心组件. 2.

分块入门

版权申明:本文转自 Monica 首先,分块是什么意思呢,顾名思义就是把要处理的东西进行分块,分成一块一块的233,举个很简单的例子,对于一个数列 size(a{ })=5,我们可以把前2个分到一起,再两个分到一起,最后单下来一个,为什么要这样处理呢?这样处理的好处又是什么呢? 我们也可以这样思考,如果我们把一个数列,当该数列的长度为n的时候,我们以根号n为一段,分出来的段数不超过根号n,如果我们要进行区间的处理,比如加法减法等,可以对于修改区间[ L , R ]可以把其中框起来的块(一块是根号

【OpenCV入门教程之四】 ROI区域图像叠加&amp;初级图像混合 全剖析(转)

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/20911629 作者:毛星云(浅墨)    邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.8 在这篇文章里,我们一起学习了在OpenCV中如何定义感兴趣区域ROI,如何使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像

周(月)总结 ------------ 5月10日,祝全天下母亲母亲节快乐。

好吧. 让我们谈点正(che)经(dan)的事. 细数一数这周(月)都干了点啥. 5月1~3 首先,颓了一整个五一,今天去那个亲戚明天看这个的- -.整个五一就是颓过去了,五一的那个ch的比赛被虐的跟狗一样,递推都想不到,鬼知道当时自己中什么邪了. Conclude:在家的效率低的不行,这点已经注意了!= = 5月4~10 咳,这一周,个人评价60分吧,具体为什么呢,这一周的状态的确比以前好多了,不过在面对一些傻题的时候做不到1A,代码准确度不够,(不过现在好多了),尤其是面对傻题却想不到,这简

「日常训练与知识学习」树的分块(王室联邦,HYSBZ-1086)

题意与分析 这题的题意就是树分块,更具体的看题目(中文题). 学习这一题是为了树的分块,为树上莫队做铺垫. 参考1:https://blog.csdn.net/LJH_KOQI/article/details/52326103 参考2:https://blog.csdn.net/popoqqq/article/details/42772237 注意到题目要求某块区域所有的点到根的路径上的点都属于该区域.因此不能够暴力地去dfs,每找到\(B\)个分一块是不可取的,因为无法保证联通性(一颗子树的下

BZOJ 3343: 教主的魔法 [分块]【学习笔记】

3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1172  Solved: 526[Submit][Status][Discuss] Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)

matlab学习笔记,图像分块

clc; clear all; close all; I = imread('E:\matlab\files-images\tomsen512.jpg'); rs = size(I, 1);% 行数cs = size(I, 2); % 列数% ch为列间隔 cw为行间隔 ,控制分块图像的大小,如现在的8*8% numr为间隔块个数 numc为间隔块个数ch = 8;   cw = 8; numr = round(rs/ch); numc = round(cs/cw); % 区域块分割t1 = (