1.区间更新单点查询

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
int n, len, pos[maxn], a[maxn];
struct Block {
int add;
} b[];
void update(int l, int r, int c) {
int p = pos[l], q = pos[r];
if (p == q)
for (int i = l; i <= r; i++) a[i] += c;
else {
for (int i = p + ; i <= q - ; i++) b[i].add += c;
for (int i = l; i <= p * len; i++) a[i] += c;
for (int i = (q - ) * len + ; i <= r; i++) a[i] += c;
}
}
int main() {
cin >> n;
len = sqrt(n);
for (int i = ; i <= n; i++) cin >> a[i];
for (int i = ; i <= n; i++) pos[i] = (i - ) / len + ;
int opt, l, r, c;
for (int i = ; i <= n; i++) {
scanf("%d%d%d%d", &opt, &l, &r, &c);
if (opt == )
update(l, r, c);
else
cout << a[r] + b[pos[r]].add << '\n';
}
}

2.区间求小于c的数的个数:先预处理,即把每块的元素sort一下,整块修改用add标记,查询用lower_bound,两端修改后用sort维护,查询暴力统计即可

注意要把add当做块的属性,而不要下放到块中的元素里去

/*
预处理块时需要将块内元素进行排序,然后可以每次查询都是用二分来做
区间更新时要将两端元素进行单独修改+排序
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 50005
struct Block {
int add;
vector<int> v;
} b[];
int n, pos[maxn], len;
int a[maxn]; inline void calc(int p) {
b[p].v.clear();
for (int i = (p - ) * len + ; i <= min(p * len, n); i++) b[p].v.push_back(a[i]);
sort(b[p].v.begin(), b[p].v.end());
}
void update(int l, int r, int c) {
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) a[i] += c;
calc(p);
return;
}
for (int i = p + ; i <= q - ; i++) b[i].add += c;
for (int i = l; i <= min(p * len, n); i++) a[i] += c;
for (int i = (q - ) * len + ; i <= r; i++) a[i] += c;
calc(p);
calc(q);
}
int query(int l, int r, int c) {
int res = ;
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++)
if (a[i] + b[p].add < c)
res++;
return res;
}
for (int i = p + ; i <= q - ; i++) {
int x = c - b[i].add;
int tmp = lower_bound(b[i].v.begin(), b[i].v.end(), x) - b[i].v.begin();
res += tmp;
}
for (int i = l; i <= min(p * len, n); i++)
if (a[i] + b[p].add < c)
res++;
for (int i = (q - ) * len + ; i <= r; i++)
if (a[i] + b[q].add < c)
res++;
return res;
}
int main() {
cin >> n;
len = sqrt(n);
for (int i = ; i <= n; i++) cin >> a[i];
for (int i = ; i <= n; i++) {
pos[i] = (i - ) / len + ;
b[pos[i]].v.push_back(a[i]);
}
for (int i = ; i <= pos[n]; i++) //预处理先排序
sort(b[i].v.begin(), b[i].v.end());
int m = n;
while (m--) {
ll opt, l, r, c;
scanf("%d%d%d%d", &opt, &l, &r, &c);
if (opt == )
update(l, r, c);
else
cout << query(l, r, c * c) << endl;
}
}

3.区间更新+找区间内小于c的最大的数(c的前驱)

块设为sqrt(n)就会t,设为1000就没事。。玄学复杂度啊

/*
set每次修改都是logn,那么n次块内更新耗时n*sqrt(n)*logsqrt(n)
*/
#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
struct Block {
int add;
set<int> s;
} b[];
int n, pos[maxn], len, a[maxn];
set<int>::iterator it; void update(int l, int r, int c) {
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) {
b[p].s.erase(a[i]);
a[i] += c;
b[p].s.insert(a[i]);
}
return;
}
for (int i = p + ; i <= q - ; i++) b[i].add += c;
for (int i = l; i <= min(p * len, n); i++) {
b[p].s.erase(a[i]);
a[i] += c;
b[p].s.insert(a[i]);
}
for (int i = (q - ) * len + ; i <= r; i++) {
b[q].s.erase(a[i]);
a[i] += c;
b[q].s.insert(a[i]);
}
}
int query(int l, int r, int c) {
int res = -, p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) {
int x = a[i] + b[p].add;
if (x < c)
res = max(res, x);
}
return res;
}
for (int i = p + ; i <= q - ; i++) { //大块里用set查
int x = c - b[i].add;
it = b[i].s.lower_bound(x);
if (it == b[i].s.begin())
continue;
it--;
res = max(res, (*it) + b[i].add);
}
for (int i = l; i <= min(p * len, n); i++)
if (a[i] + b[p].add < c)
res = max(res, a[i] + b[p].add);
for (int i = (q - ) * len + ; i <= r; i++)
if (a[i] + b[q].add < c)
res = max(res, a[i] + b[q].add);
return res;
} int main() {
cin >> n;
len = ;
for (int i = ; i <= n; i++) scanf("%d", &a[i]);
for (int i = ; i <= n; i++) {
pos[i] = (i - ) / len + ;
b[pos[i]].s.insert(a[i]);
}
for (int i = ; i <= n; i++) {
int opt, l, r, c;
scanf("%d%d%d%d", &opt, &l, &r, &c);
if (opt == )
update(l, r, c);
else
cout << query(l, r, c) << endl;
}
}

4.区间更新,区间求和

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 50005
struct Block {
ll add, sum;
} b[];
int n, pos[maxn], len;
ll a[maxn]; void update(int l, int r, int c) {
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) a[i] += c, b[p].sum += c;
return;
}
for (int i = p + ; i <= q - ; i++) b[i].add += c;
for (int i = l; i <= min(p * len, n); i++) a[i] += c, b[p].sum += c;
for (int i = (q - ) * len + ; i <= r; i++) a[i] += c, b[q].sum += c;
}
ll query(int l, int r, int c) {
ll res = ;
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) res += a[i] + b[p].add;
return res % c;
}
for (int i = p + ; i <= q - ; i++) res += b[i].sum, res += len * b[i].add;
for (int i = l; i <= min(p * len, n); i++) res += b[p].add, res += a[i];
for (int i = (q - ) * len + ; i <= r; i++) res += b[q].add, res += a[i];
return res % c;
} int main() {
cin >> n;
len = sqrt(n);
for (int i = ; i <= n; i++) cin >> a[i];
for (int i = ; i <= n; i++) {
pos[i] = (i - ) / len + ;
b[pos[i]].sum += a[i];
}
for (int i = ; i <= n; i++) {
int opt, l, r, c;
scanf("%d%d%d%d", &opt, &l, &r, &c);
if (opt == )
update(l, r, c);
else
cout << query(l, r, c + ) << endl;
}
}

5.区间开根(类似于势能线段树)

/*
2*2=4,4*4=16,16*16=256,每个数最多被开4次,开了4次以上就是1
所以两端暴力开,整块判断块中所有元素是不是1,是的话那么这个块就不用开了
修改最多4n,查询就是n*根号n
*/
#include <bits/stdc++.h>
using namespace std;
#define maxn 50005
struct Block {
int flag;
int sum;
} b[];
int n, len, pos[maxn], a[maxn]; void calc(int p) {
if (b[p].flag)
return;
b[p].flag = ;
b[p].sum = ;
for (int i = (p - ) * len + ; i <= p * len; i++) {
a[i] = (int)sqrt(a[i]);
b[p].sum += a[i];
if (a[i] > )
b[p].flag = ;
}
}
void update(int l, int r) {
int p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) {
b[p].sum -= a[i];
a[i] = sqrt(a[i]);
b[p].sum += a[i];
}
return;
}
for (int i = p + ; i <= q - ; i++) calc(i);
for (int i = l; i <= min(r, p * len); i++) {
b[p].sum -= a[i];
a[i] = sqrt(a[i]);
b[p].sum += a[i];
}
for (int i = (q - ) * len + ; i <= r; i++) {
b[q].sum -= a[i];
a[i] = sqrt(a[i]);
b[q].sum += a[i];
}
}
int query(int l, int r) {
int res = , p = pos[l], q = pos[r];
if (p == q) {
for (int i = l; i <= r; i++) res += a[i];
return res;
}
for (int i = p + ; i <= q - ; i++) res += b[i].sum;
for (int i = l; i <= min(p * len, r); i++) res += a[i];
for (int i = (q - ) * len + ; i <= r; i++) res += a[i];
return res;
} int main() {
cin >> n;
len = sqrt(n);
for (int i = ; i <= n; i++) cin >> a[i];
for (int i = ; i <= n; i++) {
pos[i] = (i - ) / len + ;
b[pos[i]].sum += a[i];
}
for (int i = ; i <= n; i++) {
int opt, l, r, c;
cin >> opt >> l >> r >> c;
if (opt == )
update(l, r);
else
cout << query(l, r) << endl;
}
}

6.块状数组,块状链表:用来解决在数列中插入一个数

/*
块内维护一个数组和size
再用前缀和log根号n 的时间内找到新来的数应该加在哪个块中
然后每增加一个数都要消耗该数所在块的长度的时间
如果数据随机,那么一次插入就是O(根号n) 如果不随机。。可能n个数都加在同一个块内,那么会导致复杂度退化为n^2
那么当块过大时进行重构即可,这里将块大小上限设置为20*根号n
*/
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005
struct Block{
vector<int>v;
}b[];
int nn,n,len,m,pos[maxn],a[maxn];//块的长度,块的个数 void rebuild(){
nn=;
for(int i=;i<=m;i++){
for(int j=;j<b[i].v.size();j++)
a[++nn]=b[i].v[j];
b[i].v.clear();
}
len=sqrt(nn);m=(nn-)/len+;
for(int i=;i<=nn;i++){
pos[i]=(i-)/len+;
b[pos[i]].v.push_back(a[i]);
}
}
void update(int pos,int x){//在位置pos插入x
int p=;
while(b[p].v.size()<pos)
pos-=b[p].v.size(),p++;
b[p].v.insert(b[p].v.begin()+pos-,x);
if(b[p].v.size()>*len)
rebuild();
}
int query(int pos){
int p=;
while(b[p].v.size()<pos)
pos-=b[p].v.size(),p++;
return b[p].v[pos-];
}
int main(){
cin>>n;len=sqrt(n);
for(int i=;i<=n;i++)cin>>a[i];
for(int i=;i<=n;i++){
pos[i]=(i-)/len+;
b[pos[i]].v.push_back(a[i]);
}
m=pos[n];
for(int i=;i<=n;i++){
int opt,l,r,c;
cin>>opt>>l>>r>>c;
if(opt==)update(l,r);
else cout<<query(r)<<endl;
}
}

7.标记下传顺序(标记优先级)

/*
把数字表示成a*mul+add的形式
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define mod 10007
#define ll long long
struct Block{
int mul,add;
}b[];
int a[maxn],n,len,pos[maxn]; void pushdown(int p){
for(int i=(p-)*len+;i<=min(p*len,n);i++)
a[i]=((ll)a[i]*b[p].mul+b[p].add)%mod;
b[p].add=;b[p].mul=;
}/*
void add(int l,int r,int c){
int p=pos[l],q=pos[r];
if(p==q){
pushdown(p);
for(int i=l;i<=r;i++)
a[i]=(a[i]+c)%mod;
return;
}
for(int i=p+1;i<=q-1;i++)
b[i].add=(b[i].add+(ll)b[i].mul*c)%mod;
pushdown(p);pushdown(q);
for(int i=l;i<=min(p*len,r);i++)
a[i]=(a[i]+c)%mod;
for(int i=(q-1)*len+1;i<=r;i++)
a[i]=(a[i]+c)%mod;
}
void mul(int l,int r,int c){
int p=pos[l],q=pos[r];
if(p==q){
pushdown(p);
for(int i=l;i<=r;i++)
a[i]=((ll)a[i]*c)%mod;
return;
}
for(int i=p+1;i<=q-1;i++){
b[i].mul=((ll)b[i].mul*c)%mod;
b[i].add=((ll)b[i].add*c)%mod;
}
pushdown(p);pushdown(q);
for(int i=1;i<=min(p*len,r);i++)
a[i]=((ll)a[i]*c)%mod;
for(int i=(q-1)*len+1;i<=r;i++)
a[i]=((ll)a[i]*c)%mod;
}*/
void update(int f,int l,int r,int c){
int p=pos[l],q=pos[r];
pushdown(p);
for(int i=l;i<=min(r,p*len);i++){
if(f==)a[i]+=c;
else a[i]*=c;
a[i]%=mod;
}
if(p!=q){
pushdown(q);
for(int i=(q-)*len+;i<=r;i++){
if(f==)a[i]+=c;
else a[i]*=c;
a[i]%=mod;
}
}
for(int i=p+;i<=q-;i++){
if(f==)
b[i].add=(b[i].add+c)%mod;
else {
b[i].mul=(b[i].mul*c)%mod;
b[i].add=(b[i].add*c)%mod;
}
}
}
int query(int x){
int p=pos[x];
return ((ll)a[x]*b[p].mul+b[p].add)%mod;
}
int main(){
cin>>n;len=sqrt(n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=n;i++)
pos[i]=(i-)/len+;
for(int i=;i<=pos[n];i++)
b[i].mul=;
for(int i=;i<=n;i++){
int opt,l,r,c;
scanf("%d%d%d%d",&opt,&l,&r,&c);
if(opt==)cout<<query(r)<<endl;
else update(opt,l,r,c);
}
}

8.区间覆盖

/*
区间众数
覆盖标记 */
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
struct Block{
int c;
}b[];
int a[maxn],n,pos[maxn],len;
void pushdown(int p){
if(b[p].c!=-){
for(int i=(p-)*len+;i<=p*len;i++)
a[i]=b[p].c;
b[p].c=-;
}
}
int query(int l,int r,int c){
int res=,p=pos[l],q=pos[r];
if(p==q){
pushdown(p);
for(int i=l;i<=r;i++)
if(a[i]==c)res++;
else a[i]=c;
return res;
}
pushdown(p);pushdown(q);
for(int i=l;i<=min(p*len,r);i++)
if(a[i]==c)res++;
else a[i]=c; for(int i=(q-)*len+;i<=r;i++)
if(a[i]==c)res++;
else a[i]=c; for(int i=p+;i<=q-;i++)
if(b[i].c!=-){
if(b[i].c==c)res+=len;
else b[i].c=c;
}
else {
for(int j=(i-)*len+;j<=i*len;j++)
if(a[j]==c)res++;
else a[j]=c;
b[i].c=c;
}
return res;
} int main(){
cin>>n;len=sqrt(n);
for(int i=;i<=n;i++)cin>>a[i];
for(int i=;i<=n;i++)
pos[i]=(i-)/len+,b[pos[i]].c=-;
for(int i=;i<=n;i++){
int l,r,c;
cin>>l>>r>>c;
cout<<query(l,r,c)<<endl;
}
}

分块入门(根据hzwer的博客。。)(右端点是r不是n。。)的更多相关文章

  1. 推荐csdn里的几篇activiti基础入门及提高的博客

    昨天有个网友加qq询问我有没有非maven搭建的activiti项目的demo,因为我博客中写了一个用maven,我当时没有,于是晚上回家尝试了一下,结果比较容易就实现了. 之后和那个网友聊了一下,他 ...

  2. Flask从入门到做出一个博客的大型教程(一)

    本项目全部在虚拟环境中运行,因此请参照前面的文章,链接为https://blog.csdn.net/u014793102/article/details/80302975 建立虚拟环境后,再接着完成本 ...

  3. [python][flask] Flask 入门(以一个博客后台为例)

    目录 1.安装 1.1 创建虚拟环境 1.2 进入虚拟环境 1.3 安装 flask 2.上手 2.1 最小 Demo 2.2 基本知识 3.解构官网指导 Demo 3.1 克隆与代码架构分析 3.2 ...

  4. Python爬虫入门教程 17-100 CSD*博客抓取数据

    写在前面 写了一段时间的博客了,忽然间忘记了,其实CSD*博客频道的博客也是可以抓取的,所以我干了..... 其实这事情挺简单的,打开CSDN博客首页,他不是有个最新文章么,这个里面都是最新发布的文章 ...

  5. Jupyter 快速入门——写python项目博客非常有用!!!

    from:https://blog.csdn.net/m0_37338590/article/details/78862488 一.简介: Jupyter Notebook(此前被称为 IPython ...

  6. django入门--django-blog-zinnia搭建个人博客

    1.安装python 选择合适python2.7及以上版本安装https://www.python.org/downloads/ 2.建立虚拟环境 这不是必须的,但是建议使用,为每个项目单独引入依赖, ...

  7. Django开发个人博客入门学习经验贴

    [写在前面] 入门学习搭建个人博客系统首先还是参考大佬们的经验,记得刚入手Django的时候,一篇博客大佬说过一句话,做技术的不要一开始就扎头于细节中,先把握整体框架,了解这个对象之后再去了解细节,进 ...

  8. cnBlogs博客推荐

      数据结构和算法若可以称为为编程的细胞结构,那设计模式就是编程的灵魂气脉. 一个从是编程的微观演绎,一个是编程的宏观设计.这个从技术和艺术的结合体,毫无疑问是在世界末日之前的很伟大的一项发明. 设计 ...

  9. JavaWeb项目开发案例精粹-第4章博客网站系统-002辅助类及配置文件

    1. <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5&qu ...

随机推荐

  1. 【mmall】IDEA中Service层无法识别Mapper,但是代码通过问题

    解决方案

  2. tensorflow开发基本步骤

    Tensorflow开发的基本步骤: 定义Tensorflow输入节点 通过占位符定义: X = tf.placeholder("float") 2.通过字典类型定义: input ...

  3. 利用jTessBoxEditor工具进行Tesseract-OCR样本训练

    jTessBoxEditor依赖java虚拟机 , 所以要先安装 java. jTessBoxEditor下载地址: https://sourceforge.net/projects/vietocr/ ...

  4. pytorch1.0 用torch script导出模型

    python的易上手和pytorch的动态图特性,使得pytorch在学术研究中越来越受欢迎,但在生产环境,碍于python的GIL等特性,可能达不到高并发.低延迟的要求,存在需要用c++接口的情况. ...

  5. 统计分析与R软件-chapter2-3

    2.3 对象和它的模式与属性 R是一种基于对象的语言,R的对象包含了若干个元素作为其数据,另外还可以有一些特殊数据称为属性,并规定了一些特定操作(如打印.绘图).比如,一个向量是一个对象,一个图形也是 ...

  6. 【转】数据库介绍(MySQL安装 体系结构、基本管理)

    [转]数据库介绍(MySQL安装 体系结构.基本管理) 第1章 数据库介绍及mysql安装 1.1 数据库简介 数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新 ...

  7. go学习笔记

    安装 brew install go 国际惯例hello,world. 创建文件hello.go go文件的main方法为函数的主入口,必须有这个方法. hello.go package main i ...

  8. Liunx之KVM搭建图形化的WEB

    作者:邓聪聪 我们常在Windowns下使用VMware,当然在Liunx中也有这样的软件供我们使用.生产环境的KVM宿主机越来越多,需要对宿主机的状态进行调控.这里用webvirtmgr进行管理.图 ...

  9. C# string.join

    String.Join 方法 平常工作中经常用到string.join()方法,在vs 2017用的运行时(System.Runtime, Version=4.2.0.0)中,共有九个(重载)方法. ...

  10. 设计模式C++学习笔记之一(Strategy策略模式)

    无意中,从网上下到一本电子书<24种设计模式介绍与6大设计原则>,很好奇这里有24种设计模式,印象中GOF写的<设计模式>(Design Patterns),好像只有23种吧. ...