zoukankan      html  css  js  c++  java
  • 分块学习笔记

    分块方法:

    (n) 个元素每 (S) 个一块,分成 (lceil frac{n}{S} ceil) 个块,维护每个块的加法标记和总和。

    对于查询操作,直接把整块的加上;非整块的暴力加。

    时间复杂度:(O(2 imes S+lceil frac{n}{S} ceil))

    对于区间加操作,整块的加标记和总和;非整块的,暴力加。

    时间复杂度:(O(2 imes S+lceil frac{n}{S} ceil))

    为让时间复杂度平衡,令(S=sqrt{n}).

    可得,时间复杂度均摊为 (n imes sqrt{n})

    模板题目

    虽然效率不如之前写的线段树高,但是码量少,实现快。基于暴力的一种算法。

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const ll MOD=LONG_LONG_MAX;
    const int N=1e6+1;
    #define EPS 1e-8
    
    inline ll read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	ll x=0;while(ch>='0' && ch<='9') x=((x<<3)+(x<<1)+ch-'0')%MOD,ch=getchar();return x*f;}
    
    int n,m,S;
    ll a[N],sum[N],add[N];
    
    inline int kuai(int x) {
    	return x/S+1; //返回i属于的块的位置
    }
    
    inline void update(int l,int r,int x) {
    	int L=kuai(l),R=kuai(r);
    	if(L==R) {
    		for(int i=l;i<=r;i++) //暴力枚举这个块
    			a[i]=(a[i]+x)%MOD,sum[L]=(sum[L]+x)%MOD;
    		return;
    	}
    	for(int i=L+1;i<R;i++) sum[i]=(sum[i]+x*S)%MOD,add[i]=(add[i]+x)%MOD;
    		//中间块的枚举
    	for(int i=l;i<L*S;i++) a[i]=(a[i]+x)%MOD,sum[kuai(i)]=(sum[kuai(i)]+x)%MOD;
    		//左边到块末尾的枚举
    	for(int i=(R-1)*S;i<=r;i++) a[i]=(a[i]+x)%MOD,sum[kuai(i)]=(sum[kuai(i)]+x)%MOD;
    		//块开始到右边的枚举
    }
    
    inline ll query(int l,int r) {
    	ll ans=0; int L=kuai(l),R=kuai(r);
    	if(L==R) {
    		for(int i=l;i<=r;i++) ans=(ans+a[i]+add[L])%MOD; //暴力枚举这个块
    		return ans;
    	}
    	for(int i=L+1;i<R;i++) ans=(ans+sum[i])%MOD;
    		//中间块的枚举
    	for(int i=l;i<=L*S-1;i++) ans=(ans+a[i]+add[kuai(i)])%MOD;
    		//左边到块末尾的枚举
    	for(int i=(R-1)*S;i<=r;i++) ans=(ans+a[i]+add[kuai(i)])%MOD;
    		//块开始到右边的枚举
    	return ans;
    }
    
    int main(){
    	n=read(); m=read(); S=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),sum[kuai(i)]=(sum[kuai(i)]+a[i])%MOD;
    	while(m--) {
    		int opt=read(),l=read(),r=read();
    		if(opt==2) printf("%lld
    ",query(l,r));
    		else {
    			int x=read();
    			update(l,r,x);
    		}
    	}
    	return 0;
    }
    
    简易的代码胜过复杂的说教。
  • 相关阅读:
    编译安装mysql-5.6.36
    MYSQL数据库基础篇
    MYSQL数据库初学者必看
    Centos7下安装与卸载Jdk1.8
    Linux与Window之间的上传与下载
    MySQL主从搭建
    zabbix通过插件percona进行监控MySQL
    suse系统关闭防火墙
    编译安装zabbix3.0
    centos7安装tomcat
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12498884.html
Copyright © 2011-2022 走看看