参考:「分块」数列分块入门1 – 9 by hzwer

2

Description

给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,询问区间内小于某个值\(x\)的元素个数。

思路

每个块内保持升序排列。

则块外暴力统计,块内二分查找分界点。

一些注意点,如:

  1. 要记录下标
  2. 块外暴力修改完之后需要再排序
  3. 在块内二分查找的值是\(c-tag[i]\)而非\(c\).

Code

#include <bits/stdc++.h>
#define maxn 50010
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int tag[maxn], bl[maxn], n, blo;
struct node {
int x, p;
bool operator < (const node& nd) const { return x < nd.x; }
}a[maxn];
inline int val(int x) { return a[x].x + tag[bl[x]]; }
int query(int l, int r, int c) {
int ret=0;
F(i, bl[l]*blo, min((bl[l]+1)*blo, n)) if (a[i].p>=l&&a[i].p<=r && val(i)<c) ++ret;
if (bl[l]!=bl[r]) F(i, bl[r]*blo, min((bl[r]+1)*blo, n)) if (a[i].p>=l&&a[i].p<=r && val(i)<c) ++ret;
F(i, bl[l]+1, bl[r]) ret += lower_bound(a+i*blo, a+(i+1)*blo, (node){c-tag[i], 0}) - (a+i*blo);
return ret;
}
void add(int l, int r, int c) {
F(i, bl[l]*blo, min((bl[l]+1)*blo,n)) if (a[i].p>=l&&a[i].p<=r) a[i].x+=c;
sort(a+bl[l]*blo, a+min((bl[l]+1)*blo, n));
if (bl[l]!=bl[r]) {
F(i, bl[r]*blo, min((bl[r]+1)*blo, n)) if (a[i].p>=l&&a[i].p<=r) a[i].x+=c;
sort(a+bl[r]*blo, a+min((bl[r]+1)*blo, n));
}
F(i, bl[l]+1, bl[r]) tag[i] += c;
}
int main() {
scanf("%d", &n); blo = sqrt(n);
F(i, 0, n) scanf("%d", &a[i].x), a[i].p = i, bl[i] = i/blo;
int num = (n+blo-1)/blo;
F(i, 0, num-1) sort(a+i*blo, a+(i+1)*blo);
sort(a+(num-1)*blo, a+n);
F(i, 0, n) {
int op, l, r, c;
scanf("%d%d%d%d", &op, &l, &r, &c); --l, --r;
if (op) printf("%d\n", query(l, r, c*c));
else add(l, r, c);
}
return 0;
}

3

Description

给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,询问区间内小于某个值\(x\)的最大值。

思路

法一

做法基本同上。

法二

在每个块内用其他数据结构维护,如set,每次修改时,结合原序数组进行修改。

Code

Ver. 1

#include <bits/stdc++.h>
#define maxn 100010
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int tag[maxn], bl[maxn], n, blo;
struct node {
int x, p;
bool operator < (const node& nd) const { return x < nd.x; }
}a[maxn];
inline int val(int x) { return a[x].x + tag[bl[x]]; }
int query(int l, int r, int c) {
int ans=-1, diff=INT_MAX, temp;
F(i, bl[l]*blo, min((bl[l]+1)*blo, n)) {
if (a[i].p>=l&&a[i].p<=r && (temp=c-val(i))>0 && temp<diff) ans = val(i), diff = temp;
}
if (bl[l]!=bl[r]) F(i, bl[r]*blo, min((bl[r]+1)*blo, n)) {
if (a[i].p>=l&&a[i].p<=r && (temp=c-val(i))>0 && temp<diff) ans = val(i), diff = temp;
}
F(i, bl[l]+1, bl[r]) {
int p = lower_bound(a+i*blo, a+(i+1)*blo, (node){c-tag[i], 0}) - (a+i*blo);
if (p==0) continue;
temp = val(i*blo+p-1);
if (c-temp>0 && c-temp<diff) diff = c-temp, ans = temp;
}
return ans;
}
void add(int l, int r, int c) {
F(i, bl[l]*blo, min((bl[l]+1)*blo,n)) if (a[i].p>=l&&a[i].p<=r) a[i].x+=c;
sort(a+bl[l]*blo, a+min((bl[l]+1)*blo, n));
if (bl[l]!=bl[r]) {
F(i, bl[r]*blo, min((bl[r]+1)*blo, n)) if (a[i].p>=l&&a[i].p<=r) a[i].x+=c;
sort(a+bl[r]*blo, a+min((bl[r]+1)*blo, n));
}
F(i, bl[l]+1, bl[r]) tag[i] += c;
}
int main() {
scanf("%d", &n); blo = sqrt(n);
F(i, 0, n) scanf("%d", &a[i].x), a[i].p = i, bl[i] = i/blo;
int num = (n+blo-1)/blo;
F(i, 0, num-1) sort(a+i*blo, a+(i+1)*blo);
sort(a+(num-1)*blo, a+n);
F(i, 0, n) {
int op, l, r, c;
scanf("%d%d%d%d", &op, &l, &r, &c); --l, --r;
if (op) printf("%d\n", query(l, r, c));
else add(l, r, c);
}
return 0;
}

Ver. 2

然而我写\(T\)了

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 100010
using namespace std;
typedef long long LL;
int n, blo, bl[maxn], a[maxn], tag[maxn];
multiset<int> st[1010];
void modify(int l, int r, int c) {
F(i, l, min((bl[l]+1)*blo, r+1)) {
st[bl[l]].erase(st[bl[l]].find(a[i]));
st[bl[l]].insert(a[i]+=c);
}
if (bl[l]!=bl[r]) F2(i, bl[r]*blo, r) {
st[bl[r]].erase(st[bl[r]].find(a[i]));
st[bl[r]].insert(a[i]+=c);
}
F(i, bl[l]+1, bl[r]) tag[i] += c;
}
inline int val(int x) { return a[x] + tag[bl[x]]; }
int query(int l, int r, int c) {
int ans=-1;
F(i, l, min((bl[l]+1)*blo, r+1)) {
if (val(i)<c) ans = max(ans, val(i));
}
if (bl[l]!=bl[r]) F2(i, bl[r]*blo, r) {
if (val(i)<c) ans = max(ans, val(i));
}
F(i, bl[l]+1, bl[r]) {
auto it = st[i].lower_bound(c-tag[i]);
if (it==st[i].begin()) continue;
int x;
ans = max(ans, x=*(--it)+tag[i]);
}
return ans;
}
LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main() {
scanf("%d", &n); blo = 1000;
F(i, 0, n) {
a[i] = read();
st[bl[i]=i/blo].insert(a[i]);
}
F(i, 0, n) {
int op, l, r, c;
scanf("%d%d%d%d", &op, &l, &r, &c); --l, --r;
if (op) printf("%d\n", query(l, r, c));
else modify(l, r, c);
}
return 0;
}

loj 6278 6279 数列分块入门 2 3的更多相关文章

  1. LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))

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

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

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

  3. LOJ 6279 数列分块入门3

    嗯... 题目链接:https://loj.ac/problem/6279 这道题在分块的基础上用vc数组记录,然后最后分三块,两边暴力枚举找前驱,中间lower_bound找前驱. AC代码: #i ...

  4. LOJ#6279. 数列分块入门 3

    区间加值还是正常的操作,查找前驱的时候用lower_bound查找,然后范围所在位置的值 #include<map> #include<set> #include<cti ...

  5. #6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))

    题目链接:https://loj.ac/problem/6279 题目大意:中文题目 具体思路:按照上一个题的模板改就行了,但是注意在整块查找的时候的下标问题. AC代码: #include<b ...

  6. LibreOj 6279数列分块入门 3 练习了一下set

    题目链接:https://loj.ac/problem/6279 推荐博客:https://blog.csdn.net/qq_36038511/article/details/79725027 这题区 ...

  7. 【LOJ#6278】数列分块2

    题目大意:分块维护一个有 n 个数字的序列,有两种操作:区间加,区间查询小于某个数的元素个数.n <= 50000 预处理阶段:处理出块内元素的相对大小顺序(排序),时间复杂度为 \(O(nlo ...

  8. 【LibreOJ 6278】 数列分块入门 2 (分块)

    题目原址 给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数. code: #include<cstdio> #include<iostream& ...

  9. LibreOJ 6279 数列分块入门 3(分块+排序)

    题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x ...

随机推荐

  1. Centos7之WEB服务器

    1.安装httpd服务 输入命令:yum -y install httpd [root@N37012 ~]# yum -y install httpc Loaded plugins: fastestm ...

  2. Nginx 配置支持 WAF

    WAF(Web Application Firewall),中文名叫做“Web应用防火墙” WAF的定义是这样的:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提 ...

  3. Ajax基础知识梳理

    Ajax用一句话来说就是无须刷新页面即可从服务器取得数据.注意,虽然Ajax翻译过来叫异步JavaScript与XML,但是获得的数据不一定是XML数据,现在服务器端返回的都是JSON格式的文件. 完 ...

  4. vue 组件的书写

    简单的来说是 vue组件最核心的就是props和自定义函数,来实现组件的开发 最简单的一个组件 子组件如下: <template> <div class="bgClass& ...

  5. JZOJ 5793. 【NOIP2008模拟】小S练跑步

    5793. [NOIP2008模拟]小S练跑步 (File IO): input:run.in output:run.out Time Limits: 2000 ms  Memory Limits:  ...

  6. python单元测试用例

    demo1.py #!/usr/bin/python # encoding: utf-8 def hello(): print "i am in demo1" def add(x, ...

  7. Python 频繁请求问题: [Errno 104] Connection reset by peer

    Table of Contents 1. 记遇到的一个问题:[Errno 104] Connection reset by peer 记遇到的一个问题:[Errno 104] Connection r ...

  8. laravel5.2总结--redis使用

    一切的前提都是已经安装好了redis服务器,并且能启动(我只总结了mac的安装方法:传送门) 我自己使用的是mac系统,有个教程可以参考下,传送门: 1.安装PHP PRedis 1>PRedi ...

  9. 几条 ffmpeg 的命令

    1,获取视频的信息   ffmpeg -i video.avi 2,将图片序列合成视频   ffmpeg -f image2 -i image%d.jpg video.mpg   上面的命令会把当前目 ...

  10. IOS开发学习笔记034-UIScrollView-xib实现分页

    通过xib实现分页功能的封装 1.首先实现xib UIView 的尺寸为300*130,因为准备的图片为600*260. scrollView属性设置如下: 2.新建一个和xib同名的类 2.1 类方 ...