首页 > 编程语言 >算法随笔——分块

算法随笔——分块

时间:2023-12-06 23:11:07浏览次数:31  
标签:例题 分块 int pos sqrt 算法 区间 随笔

介绍

分块的基本思想是通过适当的划分和预处理,用空间换时间,更加接近朴素算法,是一种暴力数据结构。

例题1

例如最经典的区间修改区间查询,若用树状数组来做就显得过于麻烦了。而用线段树做这道题,虽然通用,但马亮比较大,非常不友好。于是一种 \(O(nlogn)\) 的解法出现了——分块。

思路

将整个序列分为 $\sqrt{n} $ 块,每个块长自然为 \(\sqrt{n}\),于是采用大段维护,小段朴素的思路。在查询或修改的范围 \([l,r]\) 包含完整的块时,直接通过 add 数组标记该区间整体的变化。而左右两端零散的块直接朴素枚举,肥肠暴力。

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define int ll
const int N = 2e5+5;

int n,m,a[N],L[N],R[N],pos[N],sum[N],add[N];

void modify(int l,int r,int d)
{
    int p = pos[l],q = pos[r];
    if (p == q) 
    {
        sum[p] += (r-l+1) * d;
        for (int i = l;i <= r;i++) a[i] += d;
    
        return;
    }
    
    for (int i = p+1;i <= q-1;i++) add[i] += d;
    for (int i = l ;i <= R[p];i++) a[i] += d;
    for (int i = L[q];i <= r;i++) a[i] += d;
    sum[p] += (R[p]-l+1) * d;
    sum[q] += (r-L[q]+1) * d;
}

int query(int l,int r)
{
    int p = pos[l],q = pos[r];
    ll ans = 0;
    if (p == q)
    {
        for (int i = l;i <= r;i++) ans += a[i] + add[p];
        return ans;
    }
    for (int i = p + 1;i <= q-1;i++) ans += sum[i] + add[i] * (R[i]-L[i]+1);
    for (int i = l;i <= R[p];i++) ans += a[i] + add[p];
    for (int i = L[q];i <= r;i++) ans += a[i] + add[q];
    
    return ans;
}


signed main()
{
    cin >> n >> m;
    for (int i = 1;i <= n;i++) cin >> a[i];
    int t = sqrt(n);
    
    for (int i = 1;i <= t;i++)
        L[i] = (i-1) * t + 1,R[i] = i * t;
    if (R[t] < n) t++,R[t] = n,L[t] = R[t-1] + 1;
    
    for (int i = 1;i <= t;i++)
        for (int j = L[i];j <= R[i];j++)
            pos[j] =  i,sum[i] += a[j];
    
    for (int i = 1;i <= m;i++)
    {
        char op[2];
        scanf("%s",op);
        int l,r,d;
        if (op[0] == 'Q')
        {
            cin >> l >> r;
            cout << query(l,r) << endl;
        }
        else 
        {
            cin >> l >> r >> d;
            modify(l,r,d);
        }
    }
    return 0;
}

例题2

蒲公英

本题在线求解区间众数,众数不满足区间可加性,因此若用线段树和树状数组做较难维护,所以考虑分块。

做法

  • 预处理每个区间 \([l,r]\) 中每个数出现的个数。

标签:例题,分块,int,pos,sqrt,算法,区间,随笔
From: https://www.cnblogs.com/codwarm/p/fenkuai_suanfa_suibi.html

相关文章

  • 简述LVS的工作模式和调度算法
    工作模式:NAT,TUNNEL,DR,FULLNAT算法说明rr轮询调度(Round-Robin),它将请求依次分配不同的RS节点,也就是在RS节点中均摊请求。这种算法简答,但是只适合于RS节点处理性能相差不大的情况wrr加权轮询调度(Weighted Round-Robin)它将依据不同RS节点的权值分配任务。权值较高的RS将优先获得任务,并......
  • 代码随想录算法训练营第七天| 344.反转字符串 541. 反转字符串II
    LeetCode344.反转字符串题目链接: LeetCode344思路: 定义left、right指针,将两指针对应的值反转即可 classSolution{public:voidreverseString(vector<char>&s){intn=s.size();for(intleft=0,right=n-1;left<right;++left,--right){......
  • 【Python】【OpenCV】凸轮廓和Douglas-Peucker算法
    针对遇到的各种复杂形状的主体,大多情况下,我们可以求得一个近似的多边形来简化视觉图像处理,因为多边形是由直线组成的,这样就可以准确的划分区域来便捷后续的操作。 cv2.arcLength()Method:参数:curve:要计算周长的轮廓,可以是一个矩形、圆形、多边形等封闭曲线。closed:一个布尔......
  • 双边滤波算法
      H:\CodeSet\vcg完善1\pclPrj\bilateralFunc.h//双边滤波算法floatsigma_s_=0.5;floatsigma_r_=0.5;pcl::PointCloud<pcl::PointXYZ>::PtrplcCloud1;PointCloud<pcl::Normal>::Ptrcloud_normals;doublekernel(doublex,doublesigma){retur......
  • 【数据结构和算法】搜索算法
    ①搜索最小值python的min函数返回列表中的最小项1defindexOfMin(lyst):2minIndex=03currentIndex=14whilecurrentIndex<len(lyst):5iflyst[currentIndex]<lyst[minIndex]:6minIndex=currentIndex7currentI......
  • 【数据结构和算法】排序算法
    使用swap函数来交换列表中的两项的位置1defswap(lyst,i,j):2'''交换列表中两项的位置'''3temp=lyst[i]4lyst[i]=lyst[j]5lyst[j]=temp①选择排序处于列表第一项,先找到最小项的位置,如果该位置不是列表的第一项,算法会交换这两个位置的项,然后......
  • 12.6 随笔:幼儿园关闭潮 && 现代社会的人
    1、临泉县关闭50所幼儿园首先想到是中国人口下降如此之快,然后又想到自己养老怎么办?后续看了马督公的视频才发现关了50所,其中有30多所是申请开办幼儿园后连收学生都没有收之后就注销了的;然后其他有部分是因为前一年考核不合格注销的,所以根据没有说的那么夸张。思考:(1)新闻有些假的......
  • 路径规划算法 - 求解最短路径 - Dijkstra算法
    Dijkstra算法的思想是广度优先搜索(BFS)贪心策略。是从一个顶点到其余各顶点的最短路径算法,节点边是不各自不同的权重,但都必须是正数如果是负数,则需要Bellman-Ford算法如果想求任意两点之间的距离,就需要用Floyd算法求节点0->4的最短路径每次从未标记的节点中选择距离......
  • 拒绝算法推荐,使用rss订阅消息与新闻!
    算法推荐的弊端就不说了借用RSSHub镜像网站如果你实在不会,又或者觉得麻烦,那你还可以搭其他网友的“便车”。我收集了 9 个公开的 RSShub镜像网站,它们用的都是用自己的服务器,所以在流量方面也不会有问题。服务器1 :https://rsshub.rssforever.com 服务器2 :https://rss......
  • java与算法Day1 Scanner的应用(一)
    java中使用输入需要用到java.util.Scanner。Scanner有next,nextInt,nextString,hasNext,hasNextLine等方法。使用XXX variable=Scanner.NextXXX就可以获取一个输入值。next系列的方法,他们的作用都是从键盘中接收数据。当程序执行到他们的时候,在命令行中就开始等待键盘输入了,而......