LibreOJ 数列分块入门
题目链接:https://loj.ac/problem/6277
题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,单点查值。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 iii 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。
若 opt=1\mathrm{opt} = 1opt=1,表示询问 ara_rar 的值(lll 和 ccc 忽略)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0
样例输出
2
5
数据范围与提示
对于 100% 100\%100% 的数据,1≤n≤50000,−231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤231−1。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 5e4+; int block;
int a[MAXN], lazy[MAXN];
void add(int pos, int c)
{
int B = pos/block;
for(int i = ; i<B; i++) lazy[i] += c;
for(int i = B*block; i<=pos; i++) a[i] += c;
} int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
block = sqrt(n);
for(int i = ; i<n; i++)
scanf("%d", &a[i]);
int opt, l, r, c;
memset(lazy, , sizeof(lazy));
for(int i = ; i<n; i++)
{
scanf("%d%d%d%d",&opt,&l,&r,&c);
l--; r--;
if(opt==)
{
add(r,c);
if(l!=) add(l-,-c);
}
else
printf("%d\n", a[r]+lazy[r/block]);
}
}
}
题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的元素个数。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 i 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。
若 opt=1\mathrm{opt} = 1opt=1,表示询问 [l,r][l, r][l,r] 中,小于 c2c^2c2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
数据范围与提示
对于 100% 100\%100% 的数据,1≤n≤50000,−231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤231−1。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, block;
int a[MAXN], tmp[MAXN], lazy[MAXN];
vector<int> v[MAXN];
void add(int pos, int c)
{
int B = pos/block;
for(int i = ; i<B; i++) lazy[i] += c;
for(int i = B*block; i<=pos; i++) a[i] += c;
for(int i = B*block; i<min(n,B*block+block); i++) tmp[i] = a[i];
sort(tmp+B*block,tmp+min(n,B*block+block));
} int query(int pos, int c)
{
int ret = ;
int B = pos/block;
for(int i = ; i<B; i++)
ret += lower_bound(tmp+i*block, tmp+i*block+block, c*c-lazy[i]) - (tmp+i*block); for(int i = B*block; i<=pos; i++)
if(a[i]+lazy[B]<c*c) ret++;
/*
错误:
ret += lower_bound(tmp+B*block, tmp+pos+1, c*c-lazy[B]) - (tmp+B*block);
*/
return ret;
} int main()
{
while(scanf("%d", &n)!=EOF)
{
block = sqrt(n);
for(int i = ; i<n; i++)
scanf("%d", &a[i]), tmp[i] = a[i]; for(int i = ; i<block; i++)
sort(tmp+i*block, tmp+i*block+block);
sort(tmp+block*block, tmp+n); int opt, l, r, c;
memset(lazy, , sizeof(lazy));
for(int i = ; i<n; i++)
{
scanf("%d%d%d%d", &opt,&l,&r,&c);
l--; r--;
if(opt==)
{
add(r,c);
if(l) add(l-, -c);
}
else
{
int ans = query(r, c);
if(l) ans -= query(l-, c);
printf("%d\n", ans);
}
}
}
}
题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的前驱(比其小的最大元素)。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 i 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。
若 opt=1\mathrm{opt} = 1opt=1,表示询问 [l,r][l, r][l,r] 中 ccc 的前驱的值(不存在则输出 −1-1−1)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
样例输出
3
-1
数据范围与提示
对于 100% 100\%100% 的数据,1≤n≤100000,−231≤others 1 \leq n \leq 100000, -2^{31} \leq \mathrm{others}1≤n≤100000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤231−1。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, block;
int a[MAXN], tmp[MAXN], lazy[MAXN];
vector<int> v[MAXN]; void reset(int B)
{
for(int i = B*block; i<min(n,B*block+block); i++) tmp[i] = a[i];
sort(tmp+B*block,tmp+min(n,B*block+block));
} void add(int l, int r, int c)
{
int lB = l/block, rB = r/block;
for(int i = l; i<=min(r,lB*block+block-); i++) a[i] += c;
reset(lB); for(int i = lB+; i<=rB-; i++) lazy[i] += c;
if(lB!=rB)
{
for(int i = rB*block; i<=r; i++) a[i] += c;
reset(rB);
}
} int query(int l, int r, int c)
{
int ret = -;
int lB = l/block, rB = r/block;
for(int i = l; i<=min(r,lB*block+block-); i++)
if(a[i]+lazy[lB]<c) ret = max(ret, a[i]+lazy[lB]);
for(int i = lB+; i<=rB-; i++)
{
int cnt = lower_bound(tmp+i*block, tmp+i*block+block, c-lazy[i]) - (tmp+i*block);
if(cnt) ret = max(ret, tmp[i*block+cnt-]+lazy[i]);
}
if(lB!=rB)
{
for(int i = rB*block; i<=r; i++)
if(a[i]+lazy[rB]<c) ret = max(ret, a[i]+lazy[rB]);
}
return ret;
} int main()
{
while(scanf("%d", &n)!=EOF)
{
block = sqrt(n);
for(int i = ; i<n; i++)
scanf("%d", &a[i]), tmp[i] = a[i]; for(int i = ; i<block; i++)
sort(tmp+i*block, tmp+i*block+block);
sort(tmp+block*block, tmp+n); int opt, l, r, c;
memset(lazy, , sizeof(lazy));
for(int i = ; i<n; i++)
{
scanf("%d%d%d%d", &opt,&l,&r,&c);
l--; r--;
if(opt==) add(l,r,c);
else printf("%d\n", query(l,r, c));
}
}
}
题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间开方,区间求和。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 i 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都开方。
若 opt=1\mathrm{opt} = 1opt=1,表示询问位于 [l,r][l, r][l,r] 的所有数字的和。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
样例输出
6
2
数据范围与提示
对于 100% 100\%100% 的数据,1≤n≤50000,−231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤231−1。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+; int n, block;
int a[MAXN], tmp[MAXN], cnt[MAXN], vis[MAXN], sum[MAXN];
void add(int l, int r)
{
int lB = l/block, rB = r/block;
for(int i = l; i<=min(r,lB*block+block-); i++)
{
int val = sqrt(a[i]);
sum[lB] += val - a[i];
a[i] = val;
if((val==||val==)&&!vis[i])
vis[i] = , cnt[lB]--;
} for(int i = lB+; i<=rB-; i++)
if(cnt[i])
{
for(int j = i*block; j<i*block+block; j++)
{
int val = sqrt(a[j]);
sum[i] += val-a[j];
a[j] = val;
if((val==||val==)&&!vis[j])
vis[j] = , cnt[i]--;
}
}
if(lB!=rB)
{
for(int i = rB*block; i<=r; i++)
{
int val = sqrt(a[i]);
sum[rB] += val - a[i];
a[i] = val;
if((val==||val==)&&!vis[i])
vis[i] = , cnt[rB]--;
}
}
} int query(int l, int r)
{
int ret = ;
int lB = l/block, rB = r/block;
for(int i = l; i<=min(r,lB*block+block-); i++)
ret += a[i];
for(int i = lB+; i<=rB-; i++)
ret += sum[i];
if(lB!=rB)
{
for(int i = rB*block; i<=r; i++)
ret += a[i];
}
return ret;
} int main()
{
while(scanf("%d", &n)!=EOF)
{
block = sqrt(n);
memset(cnt, , sizeof(cnt));
memset(vis, , sizeof(vis));
memset(sum, , sizeof(sum));
for(int i = ; i<n; i++)
scanf("%d", &a[i]), cnt[i/block]++, sum[i/block] += a[i]; int opt, l, r, c;
for(int i = ; i<n; i++)
{
scanf("%d%d%d%d", &opt,&l,&r,&c);
l--; r--;
if(opt==) add(l,r);
else printf("%d\n", query(l,r));
}
}
}
LibreOJ 数列分块入门的更多相关文章
- LOJ6277~6285 数列分块入门
Portals 分块需注意的问题 数组大小应为,因为最后一个块可能会超出的范围. 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 数列分块入门 1 给出一个长为的数列, ...
- 数列分块入门九题(三):LOJ6283~6285
Preface 最后一题我一直觉得用莫队是最好的. 数列分块入门 7--区间乘法,区间加法,单点询问 还是很简单的吧,比起数列分块入门 7就多了个区间乘. 类似于线段树,由于乘法的优先级高于加法,因此 ...
- 数列分块入门九题(二):LOJ6280~6282
Preface 个人感觉这中间的三题是最水的没有之一 数列分块入门 4--区间加法,区间求和 这个也是很多数据结构完爆的题目线段树入门题,但是练分块我们就要写吗 修改还是与之前类似,只不过我们要维护每 ...
- 数列分块入门九题(一):LOJ6277~6279
Preface 分块,一个神奇的暴力算法.可以把很多\(O(n^2)\)的数据结构题的暴力优化到常数极小的\(O(n\sqrt n)\).当一些毒瘤题无法用线段树,主席树,平衡树,树状数组...... ...
- LOJ6285 数列分块入门9(分块)
昨天对着代码看了一晚上 然后今天终于在loj上过了 数列分块入门9题撒花★,°:.☆( ̄▽ ̄)/$:.°★ . 然后相当玄学 块的大小调成\(\sqrt{n}\)会TLE,改成150就过了 啧 然后就 ...
- LOJ 6277:数列分块入门 1(分块入门)
#6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 3 测试数据 题目描述 给出一 ...
- LOJ #6285. 数列分块入门 9-分块(查询区间的最小众数)
#6285. 数列分块入门 9 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给 ...
- LOJ #6284. 数列分块入门 8-分块(区间查询等于一个数c的元素,并将这个区间的所有元素改为c)
#6284. 数列分块入门 8 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给出 ...
- LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)
#6283. 数列分块入门 7 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给出 ...
随机推荐
- Azkban上传文件报错installation Failed.Error chunking
azkaban 上传文件报错Caused by: java.sql.SQLException: The size of BLOB/TEXT data inserted in one transacti ...
- 2017.2.20 activiti实战--第五章--用户与组及部署管理(一)用户与组
学习资料:<Activiti实战> 第五章 用户与组及部署管理(一)用户与组 内容概览:讲解activiti中内置的一套用户.组的关系,以及如何通过API添加.删除.查询. 5.1 用户与 ...
- [Django]中建立数据库视图
Django中建立数据库视图 Django中没有建立视图的接口.假设要建立一个视图须要一些手动的改变. 这里使用的Django 版本号>1.5, 使用的数据库为mysql 第一步 建立视图,比如 ...
- AutoCAD如何输入文字
1 运行文字命令(这里使用单行文字),然后鼠标点击文字的起始点,如图所示 2 鼠标分别向上和向右移动一定距离,表示文字的高度(文字的大小)和文字的旋转角度(一般向右,因为是水平文字) 3 最后 ...
- 升级Jekyll 3.0
每一次的升级都得又一次折腾一次,jekyll也不例外 从jekyll 2.5.2 升级为jekyll 3.0.1 错误一: jekyll 3.0.1 | Error: Permission denie ...
- hibernate 数据缓存
http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html,
- Shell脚本之:if-else
Shell 有三种 if ... else 语句: 1.if ... fi 语句: 2.if ... else ... fi 语句: 3.if ... elif ... else ... fi 语句. ...
- 【Python】向函数传递列表
向函数传递列表 在实际使用中你会发现,向函数传递列表是比较实用的,这种列表可能包含名字.数字.可能更复杂的对象(字典) 假设向一个函数传递一堆水果,我们说出我们喜欢所有的水果 def Obj(frui ...
- (四)DOM对象和jQuery对象
学习jQuery,需要搞清楚DOM对象和jQuery对象的关系与区别,因为两者的方法并不共用,如果搞不清楚对象类型就会导致调用错误的方法. DOM(Document Object Model)称为文档 ...
- 11-BeautifulSoup库详解
---恢复内容开始--- 灵活又方便的网页解析库,处理高效,支持多种解析器. 利用它不用编写正则表达式即可方便地实现网页信息的提取. 这个库有四个主要方法吧,其中xlml是最常用的,他的标签选择器可以 ...