• 【LibreOJ 6277】数列分块入门 1 (分块)


    emmm…学下分块~
    区间:数列中连续一段的元素
    区间操作:将某个区间[a,b]的所有元素进行某种改动的操作
    块:我们将数列划分成若干个不相交的区间,每个区间称为一个块
    整块:在一个区间操作时,完整包含于区间的块
    不完整的块:在一个区间操作时,只有部分包含于区间的块,即区间左右端点所在的两个块

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。
    时间复杂度取决于你分块的大小,可以尝试改动来优化也可以通过数学推导(显然我做不到QAQ)
    code:

    //By Menteur_Hxy
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #define ll long long
    using namespace std;
    
    int rd() {
        int x=0,fla=1; char c=' ';
        while(c>'9'|| c<'0') {if(c=='-') fla=-fla; c=getchar();}
        while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
        return x*fla;
    }
    
    const int MAX=50010;
    int n,blo;
    int v[MAX],tag[MAX],bl[MAX];
    
    void add(int a,int b,int c) {
        for(register int i=a;i<=min(bl[a]*blo,b);i++) v[i]+=c;
        if(bl[a]!=bl[b])
            for(register int i=(bl[b]-1)*blo+1;i<=b;i++) v[i]+=c;
        for(register int i=bl[a]+1;i<=bl[b]-1;i++) tag[i]+=c;
    }
    
    int main() {
        n=rd(),blo=sqrt(n)/2;
        for(register int i=1;i<=n;i++) v[i]=rd();
        for(register int i=1;i<=n;i++) bl[i]=(i-1)/blo+1;
        for(register int i=1;i<=n;i++) {
            int opt,l,r,c;
            scanf("%d %d %d %d",&opt,&l,&r,&c);
            if(!opt) add(l,r,c);
            else printf("%d
    ",v[r]+tag[bl[r]]);
        }
        return 0;
    }
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    为网站设置自定义404错误页面
    iOS核心动画
    Java 匿名内部类的示例介绍
    理解SimpleExpandableListAdapter的构造函数
    Android 控件之Spinner
    ExpandableListView 和 ExpandableListActivity的使用及数据更新
    Android中 RatingBar评分条的使用
    IHttphandler之Url重写
    DOTA版设计模式——开篇
    IHttphandler之图片水印
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9247992.html
Copyright © 2020-2023  润新知