分块入门(根据hzwer的博客。。)(右端点是r不是n。。)
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。。)的更多相关文章
- 推荐csdn里的几篇activiti基础入门及提高的博客
昨天有个网友加qq询问我有没有非maven搭建的activiti项目的demo,因为我博客中写了一个用maven,我当时没有,于是晚上回家尝试了一下,结果比较容易就实现了. 之后和那个网友聊了一下,他 ...
- Flask从入门到做出一个博客的大型教程(一)
本项目全部在虚拟环境中运行,因此请参照前面的文章,链接为https://blog.csdn.net/u014793102/article/details/80302975 建立虚拟环境后,再接着完成本 ...
- [python][flask] Flask 入门(以一个博客后台为例)
目录 1.安装 1.1 创建虚拟环境 1.2 进入虚拟环境 1.3 安装 flask 2.上手 2.1 最小 Demo 2.2 基本知识 3.解构官网指导 Demo 3.1 克隆与代码架构分析 3.2 ...
- Python爬虫入门教程 17-100 CSD*博客抓取数据
写在前面 写了一段时间的博客了,忽然间忘记了,其实CSD*博客频道的博客也是可以抓取的,所以我干了..... 其实这事情挺简单的,打开CSDN博客首页,他不是有个最新文章么,这个里面都是最新发布的文章 ...
- Jupyter 快速入门——写python项目博客非常有用!!!
from:https://blog.csdn.net/m0_37338590/article/details/78862488 一.简介: Jupyter Notebook(此前被称为 IPython ...
- django入门--django-blog-zinnia搭建个人博客
1.安装python 选择合适python2.7及以上版本安装https://www.python.org/downloads/ 2.建立虚拟环境 这不是必须的,但是建议使用,为每个项目单独引入依赖, ...
- Django开发个人博客入门学习经验贴
[写在前面] 入门学习搭建个人博客系统首先还是参考大佬们的经验,记得刚入手Django的时候,一篇博客大佬说过一句话,做技术的不要一开始就扎头于细节中,先把握整体框架,了解这个对象之后再去了解细节,进 ...
- cnBlogs博客推荐
数据结构和算法若可以称为为编程的细胞结构,那设计模式就是编程的灵魂气脉. 一个从是编程的微观演绎,一个是编程的宏观设计.这个从技术和艺术的结合体,毫无疑问是在世界末日之前的很伟大的一项发明. 设计 ...
- JavaWeb项目开发案例精粹-第4章博客网站系统-002辅助类及配置文件
1. <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5&qu ...
随机推荐
- 关于each other terminal
LD_LIBRARY_PATH shouldn't contain the current directory I am trying to build a self-contain GLIBC 2. ...
- 假设result 是一个float型变量,value是一个int型变量。执行以下赋值语句以后,变量value将是什么类型?为什么?
假设result 是一个float型变量,value是一个int型变量.执行以下赋值语句以后,变量value将是什么类型?为什么? 在执行这条语句的过程中,保存在vulue变量中的值被读取出来并转化为 ...
- 顶层const
顶层const:指针本身是一个常量 底层const:指针所指对象是一个常量 顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型.类.指针等 底层const则与指针和引用等复 ...
- Css - 字体图标
Css - 字体图标 字体格式 ttf.otf.woff.svg.eot 现在流行将图标做成矢量的字体格式的文档,很多用户在放大页面的时候页面上的普通图片格式的图标就会变得模糊不清,这种字体图标在网页 ...
- setValuesForKeysWithDictionary:的用途
setValuesForKeysWithDictionary :今天发现这个高大上的功能,让我心奋不已,以后妈妈再也不用担心模型属性多了,再也不用担心将字典中的值赋值到模型中的麻烦操作了. 模型的.h ...
- CF1100D Dasha and Chess
题目地址:CF1100D Dasha and Chess 这是我的第一道交互题 思路不难,主要讲讲这条语句: fflush(stdout); stdout是标准输出的意思.因为有时候,我们输出到std ...
- SQL Server - NOLOCK
NOLOCK 一般用于此类语句中:select * from t with(NOLOCK)nolock是不加锁查询,可以读取被事务锁定的数据,也称为脏读.说明:使当前会话的查询,不受其它会话的事务所阻 ...
- LwIP Application Developers Manual5---高层协议之DHCP,AUTOIP,SNMP,PPP
1.前言 本文主要讲述高层协议,包括DHCP 2.DHCP 2.1 从应用的角度看DHCP 你必须确保在编译和链接时使能DHCP,可通过在文件lwipopts.h里面定义LWIP_DHCP选项,该选项 ...
- Python运维开发基础10-函数基础【转】
一,函数的非固定参数 1.1 默认参数 在定义形参的时候,提前给形参赋一个固定的值. #代码演示: def test(x,y=2): #形参里有一个默认参数 print (x) print (y) t ...
- POJ3580 SuperMemo splay伸展树,区间操作
题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...