参考:「分块」数列分块入门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. Android系统编译环境及连接工具配置

    首先附上官网上关于环境搭建的地址:https://source.android.com/setup/build/initializing 官网目前建议的还是Ubuntu14.04,下面就是用的Ubun ...

  2. 关于poi的坑

    背景故事 今天遇上一个坑,关于poi公式计算结果出错的问题,自己打断点debug了半天,虽然没彻底搞清楚为啥不行,但所幸找到了解决办法. 干货 下面不废话,直接贴干货,原先的公式处理代码如下: fin ...

  3. crontab -e 和/etc/crontab的区别

    /etc/crontab文件和crontab -e命令区别/etc/crontab文件和crontab -e命令区别 1.格式不同 前者 # For details see man 4 crontab ...

  4. stm32之PWM博客好文收藏

    https://www.cnblogs.com/jiwangbujiu/p/5616376.html STM32F103 使用TIM3产生四路PWM https://www.cnblogs.com/c ...

  5. Face The Right Way POJ - 3276 (开关问题)

    Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6707   Accepted: 312 ...

  6. SpringMVC controller接收的中文参数乱码

    CharacterEncodingFilter只对POST请求有用,GET请求的需要对你运行的tomcat 目录conf/server.xml文件中<Connector connectionTi ...

  7. 爬虫工程师常用的 Chrome 插件

    做多了爬虫都知道,写一个爬虫大部分时间不是在代码上,而是在分析网页上,所有有一套好用的工具可以极大节省劳动力,这里把平时积累的一些 Chrome 插件分享出来,均来自本人和同事推荐,并不定时更新,欢迎 ...

  8. 序列化模块--json模块--pickle模块-shelve模块

    什么叫序列化? 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传播到远程,因为硬盘或网络传输时只能接受bytes 例: 把内存数据 转成字符 # data ={# 'roles ...

  9. Feign请求报请求超时

    Feign的底层基于Rabbion实现的,一般情况下直接导入feign的依赖,然后调用feignClient去发送请求,报请求超时. application.yml #hystrix的超时时间 hys ...

  10. 数据库——初始mysql语句(2)

    sql语句 #1. 操作文件夹(库) 增:create database db1 charset utf8; 查:show create database db1; show databases; 改 ...