• loj#6277. 数列分块入门 1


    #6277. 数列分块入门 1

    题目:传送门 

    简要题意:

       对于一个长度为n的数列进行区间加法修改和单点询问。


    题解:

       做分块的题需要一定的知识基础,这里就不一一讲解了,主要讲应用到每道题目是的具体做法:

       对于单点询问相对比较简单,数组简单存储之后就可以O(1)输出。

       主要就是对于区间修改:

       分块之后,对于需要修改的L~R的区间,可以简单分情况讨论:

       1、如果l和r同属一块,那么直接枚举修改

       2、如果不属于同一块,那么先将左端点所属的块从L开始到该块结尾修改,再将右端点所属的块从该块开头到R修改

       然后就是修改中间没有涉及到的块了,其实也是直接暴力,用一个新的数组统计该块整块都增加的值,枚举L的下一个块到R的上一个块就OK


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 int n,a[51000],ba[51000];
     8 int block,pos[51000];
     9 void update(int l,int r,int c)
    10 {
    11     for(int i=l;i<=min(pos[l]*block,r);i++)a[i]+=c;
    12     if(pos[l]!=pos[r])
    13         for(int i=(pos[r]-1)*block+1;i<=r;i++)
    14             a[i]+=c;
    15     for(int i=pos[l]+1;i<=pos[r]-1;i++)ba[i]+=c;
    16 }
    17 int main()
    18 {
    19     scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    20     block=sqrt(n);
    21     for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
    22     for(int i=1;i<=n;i++)
    23     {
    24         int l,r,c,opt;
    25         scanf("%d%d%d%d",&opt,&l,&r,&c);
    26         if(opt==0)update(l,r,c);
    27         else printf("%d
    ",a[r]+ba[pos[r]]);
    28     }
    29     return 0;
    30 }
  • 相关阅读:
    《鱼嘤嘤小分队》第一次作业:项目选题
    第一次博客作业
    csp 201709-2 优先队列模拟
    csp 201403-2
    csp 201809-2 买菜
    JavaScript中伪协议
    修改placeholder的样式
    jQuery对象与DOM对象之间的转换方法
    a的样式
    Guid.NewGuid() 和 new Guid()的区别
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8548715.html
Copyright © 2020-2023  润新知