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[1000];
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 + 1; i <= q - 1; i++) b[i].add += c;for (int i = l; i <= p * len; i++) a[i] += c;for (int i = (q - 1) * len + 1; i <= r; i++) a[i] += c;}
}
int main() {cin >> n;len = sqrt(n);for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) pos[i] = (i - 1) / len + 1;int opt, l, r, c;for (int i = 1; i <= n; i++) {scanf("%d%d%d%d", &opt, &l, &r, &c);if (opt == 0)update(l, r, c);elsecout << 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[5005];
int n, pos[maxn], len;
int a[maxn];inline void calc(int p) {b[p].v.clear();for (int i = (p - 1) * len + 1; 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 + 1; i <= q - 1; i++) b[i].add += c;for (int i = l; i <= min(p * len, n); i++) a[i] += c;for (int i = (q - 1) * len + 1; i <= r; i++) a[i] += c;calc(p);calc(q);
}
int query(int l, int r, int c) {int res = 0;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 + 1; i <= q - 1; 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 - 1) * len + 1; i <= r; i++)if (a[i] + b[q].add < c)res++;return res;
}
int main() {cin >> n;len = sqrt(n);for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) {pos[i] = (i - 1) / len + 1;b[pos[i]].v.push_back(a[i]);}for (int i = 1; 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 == 0)update(l, r, c);elsecout << 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[1005];
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 + 1; i <= q - 1; 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 - 1) * len + 1; 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 = -1, 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 + 1; i <= q - 1; 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 - 1) * len + 1; 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 = 1500;for (int i = 1; i <= n; i++) scanf("%d", &a[i]);for (int i = 1; i <= n; i++) {pos[i] = (i - 1) / len + 1;b[pos[i]].s.insert(a[i]);}for (int i = 1; i <= n; i++) {int opt, l, r, c;scanf("%d%d%d%d", &opt, &l, &r, &c);if (opt == 0)update(l, r, c);elsecout << 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[500];
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 + 1; i <= q - 1; 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 - 1) * len + 1; i <= r; i++) a[i] += c, b[q].sum += c;
}
ll query(int l, int r, int c) {ll res = 0;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 + 1; i <= q - 1; 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 - 1) * len + 1; i <= r; i++) res += b[q].add, res += a[i];return res % c;
}int main() {cin >> n;len = sqrt(n);for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) {pos[i] = (i - 1) / len + 1;b[pos[i]].sum += a[i];}for (int i = 1; i <= n; i++) {int opt, l, r, c;scanf("%d%d%d%d", &opt, &l, &r, &c);if (opt == 0)update(l, r, c);elsecout << query(l, r, c + 1) << 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[500];
int n, len, pos[maxn], a[maxn];void calc(int p) {if (b[p].flag)return;b[p].flag = 1;b[p].sum = 0;for (int i = (p - 1) * len + 1; i <= p * len; i++) {a[i] = (int)sqrt(a[i]);b[p].sum += a[i];if (a[i] > 1)b[p].flag = 0;}
}
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 + 1; i <= q - 1; 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 - 1) * len + 1; 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 = 0, 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 + 1; i <= q - 1; i++) res += b[i].sum;for (int i = l; i <= min(p * len, r); i++) res += a[i];for (int i = (q - 1) * len + 1; i <= r; i++) res += a[i];return res;
}int main() {cin >> n;len = sqrt(n);for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) {pos[i] = (i - 1) / len + 1;b[pos[i]].sum += a[i];}for (int i = 1; i <= n; i++) {int opt, l, r, c;cin >> opt >> l >> r >> c;if (opt == 0)update(l, r);elsecout << 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[20005];
int nn,n,len,m,pos[maxn],a[maxn];//块的长度,块的个数 void rebuild(){nn=0;for(int i=1;i<=m;i++){for(int j=0;j<b[i].v.size();j++)a[++nn]=b[i].v[j];b[i].v.clear();}len=sqrt(nn);m=(nn-1)/len+1;for(int i=1;i<=nn;i++){pos[i]=(i-1)/len+1;b[pos[i]].v.push_back(a[i]);}
}
void update(int pos,int x){//在位置pos插入x int p=1;while(b[p].v.size()<pos)pos-=b[p].v.size(),p++;b[p].v.insert(b[p].v.begin()+pos-1,x);if(b[p].v.size()>20*len)rebuild();
}
int query(int pos){int p=1;while(b[p].v.size()<pos)pos-=b[p].v.size(),p++;return b[p].v[pos-1];
}
int main(){cin>>n;len=sqrt(n);for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++){pos[i]=(i-1)/len+1;b[pos[i]].v.push_back(a[i]);}m=pos[n];for(int i=1;i<=n;i++){int opt,l,r,c;cin>>opt>>l>>r>>c;if(opt==0)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[1005];
int a[maxn],n,len,pos[maxn];void pushdown(int p){for(int i=(p-1)*len+1;i<=min(p*len,n);i++)a[i]=((ll)a[i]*b[p].mul+b[p].add)%mod;b[p].add=0;b[p].mul=1;
}/*
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==0)a[i]+=c;else a[i]*=c;a[i]%=mod;}if(p!=q){pushdown(q);for(int i=(q-1)*len+1;i<=r;i++){if(f==0)a[i]+=c;else a[i]*=c;a[i]%=mod;}    }for(int i=p+1;i<=q-1;i++){if(f==0)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=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++)pos[i]=(i-1)/len+1;for(int i=1;i<=pos[n];i++)b[i].mul=1;for(int i=1;i<=n;i++){int opt,l,r,c;scanf("%d%d%d%d",&opt,&l,&r,&c);if(opt==2)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[500];
int a[maxn],n,pos[maxn],len;
void pushdown(int p){if(b[p].c!=-1){for(int i=(p-1)*len+1;i<=p*len;i++)a[i]=b[p].c;b[p].c=-1;}
}
int query(int l,int r,int c){int res=0,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-1)*len+1;i<=r;i++)if(a[i]==c)res++;else a[i]=c;for(int i=p+1;i<=q-1;i++)if(b[i].c!=-1){if(b[i].c==c)res+=len;else b[i].c=c;}else {for(int j=(i-1)*len+1;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=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)pos[i]=(i-1)/len+1,b[pos[i]].c=-1;for(int i=1;i<=n;i++){int l,r,c;cin>>l>>r>>c;cout<<query(l,r,c)<<endl;}
}

转载于:https://www.cnblogs.com/zsben991126/p/10575330.html

分块入门(根据hzwer的博客。。)(右端点是r不是n。。)相关推荐

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

    Flask从入门到做出一个博客的大型教程(五) 在开始之前,先来看下项目的整体结构. flask/ ├── app │ ├── forms.py │ ├── __init__.py │ ├── mod ...

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

    Flask从入门到做出一个博客的大型教程(四) 在开始之前,先来看下项目的整体结构. flask ├── app │ ├── forms.py │ ├── __init__.py │ ├── mode ...

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

    Flask从入门到做出一个博客的大型教程(一) 本项目全部在虚拟环境中运行,因此请参照前面的文章,链接为https://blog.csdn.net/u014793102/article/details ...

  4. 『Python开发实战菜鸟教程』实战篇:爬虫快速入门——统计分析CSDN与博客园博客阅读数据

    文章目录 0x01:引子 首先介绍一下网络爬虫是什么,可以用来做什么? 这里简单探讨一下网络爬虫的合法性 正式进入爬虫实战前,需要我们了解下网页结构 HTML CSS JScript 写一个简单的 H ...

  5. 最新后盾网Laravel框架重入门到实战 Laravel博客项目实战 陈华主讲 包含课件源码

    老师介绍 陈华,PHP明星讲师,大学生演讲网创始人,2010年开始开发整站项目,精通Laravel,Yii框架. 简 介 本套课程是一套以项目实战为主的Laravel5.2实战开发教程,是真正意义上的 ...

  6. 浅谈代码审计入门实战:某博客系统最新版审计之旅

    身份验证漏洞 首先一上来就是一个很简单的洞,后台就可以万能密码绕过,问题出在这里ad/login.php先看代码 function jsloginpost(){ global $tabhead; gl ...

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

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

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

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

  9. 【C++基础】C++入门篇之一篇博客带你看懂为什么学习C++,C语言和C++的主要区别

    C++入门篇 C++入门 C++关键字(C++98) 命名空间 命名空间的用法 命名空间的嵌套 命名空间会被合并 命名空间的使用 C++的输入输出 缺省参数 函数重载 重载分类 重载原理 引用 引用用 ...

最新文章

  1. 保险业尚不能完全发挥CRM优势 需强化
  2. python面试常见问题-Python面试常见的8个问题及答案总结
  3. 用数字告诉你2014年Google的野心在哪里
  4. GDCM:gdcm::terminal的测试程序
  5. pandas object转float_Pandas中文官档~基础用法6
  6. Indian Buffet Process(印度自助餐过程)介绍
  7. php 删除 session 文件,如何删除php中的session文件
  8. VS2013——error C4996: 'std::_Uninitialized_copy0':
  9. VB.Net + asp.net的一个web系统,使用SQL2000数据库 现在运行时偶尔会出现一个奇怪现象,一个用户登录时,登录后的界面竟然是另一个用户...
  10. 基于arcpy包在arcmap里面实现图层的随机选取
  11. opnet中SOCKET接口开发
  12. 工行通用终端 工行 linux,在linux下用工行网银
  13. 干货《周志华机器学习详细公式推导版》发布,南瓜书pumpkin-book
  14. App Store上架之邓白氏编码申请
  15. 百度BML飞桨训练营(十)面部表情迁移PaddleGAN--蒙娜丽莎在微笑
  16. 测试路由器的防火墙配置,wan:入站数据,出站数据,转发
  17. Oracle Parallel 多线程
  18. Google Earth Engine(GEE)——User memory limit exceeded(2)
  19. python读取docx文件出错_Python:读取 .doc、.docx 两种 Word 文件简述及“Word 未能引发事件”错误...
  20. 联通MM7彩信平台技术

热门文章

  1. SAP Marketing cloud里的campaign管理
  2. SAP CRM HANA live report的数据源
  3. linux内核5.4,Linux Kernel 5.4 RC8 发布,一切都很正常
  4. python测试函数怎么写_Python - 函数
  5. kafka 0.9 java开发_kafka 0.9 java producer and consumer demo
  6. html纵向的跑马灯效果,HTML+CSS入门 如何实现跑马灯/走马灯效果
  7. 2个字节能存多少个16进制_MySql中的varchar长度究竟是字节还是字符
  8. 整数翻转Python解法
  9. 室内空气流动原理图_新风系统的工作原理是什么 新风系统各部件的用途
  10. java 数字信封_GitHub - zhopen/eos-crypto-java: EOS 公钥加密,私钥解密。基于ECC+AES 实现的双向验证加解密。数字信封的 加解密。...