loj 6278 6279 数列分块入门 2 3
参考:「分块」数列分块入门1 – 9 by hzwer
2
Description
给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,询问区间内小于某个值\(x\)的元素个数。
思路
每个块内保持升序排列。
则块外暴力统计,块内二分查找分界点。
一些注意点,如:
- 要记录下标;
- 块外暴力修改完之后需要再排序;
- 在块内二分查找的值是\(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的更多相关文章
- LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))
#6279. 数列分块入门 3 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 3 题目描述 给 ...
- LOJ 6277:数列分块入门 1(分块入门)
#6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 3 测试数据 题目描述 给出一 ...
- LOJ 6279 数列分块入门3
嗯... 题目链接:https://loj.ac/problem/6279 这道题在分块的基础上用vc数组记录,然后最后分三块,两边暴力枚举找前驱,中间lower_bound找前驱. AC代码: #i ...
- LOJ#6279. 数列分块入门 3
区间加值还是正常的操作,查找前驱的时候用lower_bound查找,然后范围所在位置的值 #include<map> #include<set> #include<cti ...
- #6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))
题目链接:https://loj.ac/problem/6279 题目大意:中文题目 具体思路:按照上一个题的模板改就行了,但是注意在整块查找的时候的下标问题. AC代码: #include<b ...
- LibreOj 6279数列分块入门 3 练习了一下set
题目链接:https://loj.ac/problem/6279 推荐博客:https://blog.csdn.net/qq_36038511/article/details/79725027 这题区 ...
- 【LOJ#6278】数列分块2
题目大意:分块维护一个有 n 个数字的序列,有两种操作:区间加,区间查询小于某个数的元素个数.n <= 50000 预处理阶段:处理出块内元素的相对大小顺序(排序),时间复杂度为 \(O(nlo ...
- 【LibreOJ 6278】 数列分块入门 2 (分块)
题目原址 给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数. code: #include<cstdio> #include<iostream& ...
- LibreOJ 6279 数列分块入门 3(分块+排序)
题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x ...
随机推荐
- 关于mybatis callSettersOnNulls 配置
今天做了一件坑了自己的事情,为此浪费了好多时间... 在mybatis的设置中,看到了这样的一行设置.出于程序员的好奇,去搜索了一下,这条设置是干什么的. <setting name=" ...
- Linux 服务器用户权限管理改造方案与实施项目
Linux 服务器用户权限管理改造方案与实施项目 在了解公司业务流程后,提出权限整改方案改进公司超级权限root泛滥的现状. 我首先撰写方案后,给boss看,取得boss的支持后,召集大家开会讨论. ...
- POJ 2763 Housewife Wind 树链拋分
一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...
- 【转】Python操作MongoDB
Python 操作 MongoDB 请给作者点赞--> 原文链接 这篇文章主要介绍了使用Python脚本操作MongoDB的教程,MongoDB作为非关系型数据库得到了很大的宣传力度,而市面 ...
- Win7系统桌面便签怎么添加?
参考:http://jingyan.baidu.com/article/ab69b270c207432ca7189f99.html Win7系统桌面便签怎么添加?有时候工作.学习忙起来就会忘记要办的事 ...
- SSH无密码登录及远程拷贝命令SCP的使用
SSH无密码登录 1.生成密钥对(公钥和私钥) $ cd /home/cen/.ssh $ ssh-keygen -t rsa #生成密钥,使用rsa方式进行加密,四个回车 $ ssh-copy-id ...
- git pull免密码拉取
ssh到服务器上,原来基于public/private key pair的方法不好使了. 1.1 创建文件存储GIT用户名和密码 在%HOME%目录中,一般为C:\users\Administrato ...
- VC下如何调用控制台命令以及其他可执行文件
开始的时候想写一个基于MFC的Wifi开关控制程序,可是不知道VC中如何调用控制台命令,经过网上的学习,发现其实挺挺简单也挺好用.于是制作了一个简单的基于MFC个人助理小软件,可以点击按钮实现Wifi ...
- xcode6没有prefix.pch预编译文件解决办法
注意到Xcode6创建的工程没有prefix.pch. 于是手动创建. 在other下选择pch文件 接着到工程的build setting下设置开启预编译并配置路径(文件的路径.因为我新建在cofi ...
- 谋哥:转型之痒与App推广之痛
昨天<重庆今日教育>的副主编汪熙坤老师先加我微信,谋哥的微信每天有几十个不同领域的朋友加.几句客套后,他马上就直奔主题了.为什么这么着急呢?是因为危机感,是因为感受到了互联网给传统纸媒带来 ...