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 题目描述 给出 ...
随机推荐
- GCC + GDB 调试方法
首先编译程序 多加一个 -g c++ test.cpp -o a -Wall -g 执行时使用 gdb a 此时输入 l 显示所有的代码 l 输入b 加入断点到某一行(break) b 108 运行 ...
- eclipse离线安装插件过程
离线安装插件: 1. help -> install New Softe.. 2. 打开安装插件界面 最后点击,next, 同意事项,重启eclipse.
- 收藏以下linux查看系统信息的命令
# uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本# hostname ...
- HDU 3591 The trouble of Xiaoqian(多重背包+全然背包)
HDU 3591 The trouble of Xiaoqian(多重背包+全然背包) pid=3591">http://acm.hdu.edu.cn/showproblem.php? ...
- JAVA Eclipse的Android文件结构是怎么样的
默认res目录下面存放了界面需要的布局和图片文件,之所以图片分为hdpi,ldpi,mdpi这些,是为了不同的设备准备的(高/中/低分辨率的图片) Bin目录类似于VS的debug或者releas ...
- frame框架及其实例
框架概念 : 谓框架便是网页画面分成几个框窗,同时取得多个 URL.只需要 <FRAMESET> <FRAME> 即可,面所有框架标记需要放在一个总起的 html 档,这个档案 ...
- java中的值传递和引用传递区别
值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响 ...
- Android学习笔记(24):进度条组件ProgressBar及其子类
ProgressBar作为进度条组件使用,它还派生了SeekBar(拖动条)和RatingBar(星级评分条). ProgressBar支持的XML属性: Attribute Name Related ...
- android一步一步实现视频clientapp(一)
我开发完毕了一个完整的视频clientapp.如今.分享出来.供刚開始学习的人学习參考(大神就不用看了,比較简单,仅供入门),大家相互交流相互学习. 项目有些功能,我时间也不是非常多.仅仅能时不时更新 ...
- 字符串== equals
经常碰到比较字符串的题, eg: public class StringDemo{ private static final String MESSAGE = "taobao"; ...