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 题目描述 给出 ...
随机推荐
- docker入门小结(二)
11,网络使用 sudo docker run -d -P training/webapp python app.py sudo docker ps -l 这样将主机一个端口映射到容器中,由于app. ...
- Netty通过心跳保持长链接
Netty自带心跳检测功能,IdleStateHandler,客户端在写空闲时主动发起心跳请求,服务器接受到心跳请求后给出一个心跳响应.当客户端在一定时间范围内不能够给出响应则断开链接. public ...
- C#日期时间类型格式化大全集 C#DateTime 类型格式化大全集
日期转化一 为了达到不同的显示效果有时,我们须要对时间进行转化,默认格式为:2007-01-03 14:33:34 ,要转化为其它格式,要用到DateTime.ToString的方法(String, ...
- Struts2学习九----------处理结果类型(input)
© 版权声明:本文为博主原创文章,转载请注明出处 Struts2处理结果类型 - SUCCESS:Action正确的执行完成,返回相应的视图,success是name属性的默认值 - ERROR:表示 ...
- 《textanalytics》课程简单总结(2):topic mining
coursera上的公开课<https://www.coursera.org/course/textanalytics>系列,讲的很不错哦. 1."term as topic&q ...
- Chrome自带恐龙小游戏的源码研究(四)
在上一篇<Chrome自带恐龙小游戏的源码研究(三)>中实现了让游戏昼夜交替,这一篇主要研究如何绘制障碍物. 障碍物有两种:仙人掌和翼龙.仙人掌有大小两种类型,可以同时并列多个:翼龙按高. ...
- spring中xml配置和autowired混用
1.类的混用: 配置文件中的配置: <bean id="a" class="com.ab.cc.A" /> 类中的配置 @Autowired A a ...
- linux启动参数了解
文章来源:http://blog.csdn.net/uyiwfn/article/details/7172339在Linux中,给kernel传递参数以控制其行为总共有三种方法:1.build ker ...
- C语言的运算符的优先级与结合性+ASCII表
[0]README 0.1) 内容来源于 C程序设计语言, 旨在整理出C语言的运算符的优先级与结合性, 如下图所示(哥子 记了大半年都没有记住,也是醉了,每次都要去翻): Alert)以下内容转自:h ...
- 爬虫学习一系列:urllib2抓取网页内容
爬虫学习一系列:urllib2抓取网页内容 所谓网页抓取,就是把URL地址中指定的网络资源从网络中读取出来,保存到本地.我们平时在浏览器中通过网址浏览网页,只不过我们看到的是解析过的页面效果,而通过程 ...