题目链接:https://loj.ac/problem/6277

题目描述

给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,单点查值。

输入格式

第一行输入一个数字 nnn。

第二行输入 nnn 个数字,第 iii 个数字为 aia_ia​i​​,以空格隔开。

接下来输入 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_ra​r​​ 的值(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,−2​31​​≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤2​31​​−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_ia​i​​,以空格隔开。

接下来输入 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^2c​2​​ 的数字的个数。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

样例输入

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,−2​31​​≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤2​31​​−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_ia​i​​,以空格隔开。

接下来输入 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,−2​31​​≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤2​31​​−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_ia​i​​,以空格隔开。

接下来输入 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,−2​31​​≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1ans≤2​31​​−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 数列分块入门的更多相关文章

  1. LOJ6277~6285 数列分块入门

    Portals 分块需注意的问题 数组大小应为,因为最后一个块可能会超出的范围. 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 数列分块入门 1 给出一个长为的数列, ...

  2. 数列分块入门九题(三):LOJ6283~6285

    Preface 最后一题我一直觉得用莫队是最好的. 数列分块入门 7--区间乘法,区间加法,单点询问 还是很简单的吧,比起数列分块入门 7就多了个区间乘. 类似于线段树,由于乘法的优先级高于加法,因此 ...

  3. 数列分块入门九题(二):LOJ6280~6282

    Preface 个人感觉这中间的三题是最水的没有之一 数列分块入门 4--区间加法,区间求和 这个也是很多数据结构完爆的题目线段树入门题,但是练分块我们就要写吗 修改还是与之前类似,只不过我们要维护每 ...

  4. 数列分块入门九题(一):LOJ6277~6279

    Preface 分块,一个神奇的暴力算法.可以把很多\(O(n^2)\)的数据结构题的暴力优化到常数极小的\(O(n\sqrt n)\).当一些毒瘤题无法用线段树,主席树,平衡树,树状数组...... ...

  5. LOJ6285 数列分块入门9(分块)

    昨天对着代码看了一晚上 然后今天终于在loj上过了 数列分块入门9题撒花★,°:.☆( ̄▽ ̄)/$:.°★ . 然后相当玄学 块的大小调成\(\sqrt{n}\)会TLE,改成150就过了 啧 然后就 ...

  6. LOJ 6277:数列分块入门 1(分块入门)

    #6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 3 测试数据 题目描述 给出一 ...

  7. LOJ #6285. 数列分块入门 9-分块(查询区间的最小众数)

    #6285. 数列分块入门 9 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给 ...

  8. LOJ #6284. 数列分块入门 8-分块(区间查询等于一个数c的元素,并将这个区间的所有元素改为c)

    #6284. 数列分块入门 8 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给出 ...

  9. LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)

    #6283. 数列分块入门 7 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给出 ...

随机推荐

  1. 重读金典------高质量C编程指南(林锐)-------第一章 文件结构

    第一章  文件结构       C/C++程序通常由两个文件组成,一个文件保存程序的声明,称为头文件,.h 文件.一个保存程序的实现,称为定义文件.c文件. 1.1 版权与版本的声明 版权和版本的声明 ...

  2. 常见的CPU訪问引起的内存保护问题为什么仅仅用event_122上报 - 举例2

    还有一个样例.通过以下的log看,CPU在訪问reserved的地址0x53611EFD.非法訪问时该地址会在L1D内存控制器的L1DMPFSR寄存器中记录. ** FATAL EXCEPTION N ...

  3. 敏捷DoD完毕定义的多种形态

    作者:张克强    作者微博:张克强-敏捷307 关于Definition of Done 完毕的定义 在以往的说法中,常见用 退出标准 , 完毕条件.成功标准,等等 在敏捷软件开发中,存在多级的不同 ...

  4. Ajax请求的跨域(CORS)问题

    用浏览器,通过XHR(XMLHttpRequest)请求向另外一个域名请求数据时.会碰到跨域(CORS)问题. CORS:Cross-Origin Resource Sharing 什么是跨域? 简单 ...

  5. webStorm 多列编辑

    webStorm可以像Sublime一样使用列编辑,只是区别在于webStorm只可以编辑连续列表. 按住alt键鼠标选择一列,然后输入文字就会编辑多行,这个功能很赞,比较实用(按住ALT键选中之后, ...

  6. python学习(一)运行第一个python脚本

    当然这里指的是在linux或者unix下,像写bash脚本那样 #!/usr/bin/python print('The Bright Side ' + 'of Life...') 反正我建议就算一开 ...

  7. 输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如:4 4 4 4-joker JOKER 请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR

    // ConsoleApplication10.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...

  8. [转]浅谈Flash Socket通信安全沙箱

    用过Flash socket的同学都知道,Flash socket通讯有安全沙箱问题.就是在Flash Player发起socket通信时,会向服务端获取安全策略,如果得不到服务端响应,flash将无 ...

  9. PHP服务端如何通过程序将图上传到指定的图片服务器与图片服务器的优化方案

    一:PHP服务端如何通过程序将图上传到指定的图片服务器与图片服务器的优化方案 (1) php服务器把图片处理成缩率图或指定大小的图片在通过PHP程序代码 操作FTP 上传到图片服务器. 二:图片服务器 ...

  10. python之异步IO

    协程的用武之地 并发量较大的系统和容易在IO方面出现瓶颈(磁盘IO,网络IO),采用多线程.多进程可以解决这个问题,当然线程.进程的切换时很消耗资源的.最好的解决方案是使用单线程方式解决并发IO问题- ...