LibreOj 6279数列分块入门 3 练习了一下set
题目链接:https://loj.ac/problem/6279
推荐博客:https://blog.csdn.net/qq_36038511/article/details/79725027
这题区间查询某个数字x的前驱(区间里比x小的最大的数),我用的是二分,自己手写二分的时候一直用的是没有排序的数组,好无语,后面又用set做了一遍,熟系一下set。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 50005*2
/*struct point{
int u,w;
};
bool operator <(const point &s1,const point &s2)
{
if(s1.w!=s2.w)
return s1.w>s2.w;
else
return s1.u>s2.u;
}*/
int n,m,k,t,block;
int a[maxn],tag[maxn],lump[maxn];
vector<int>ve[];
void update(int x)
{
ve[x].clear();//把第x块原来的值清除
for(int i=(x-)*block+;i<=min(x*block,n);i++)//这里要加min,因为第x块可能是最后一块并且是不完整的
ve[x].push_back(a[i]);//把增加了的值重新压入
sort(ve[x].begin(),ve[x].end());//排序
}
void add(int l,int r,int c)
{
for(int i=l;i<=min(lump[l]*block,r);i++)//暴力更新左边不完整的块
a[i]+=c;
update(lump[l]);//更新值并且重新排序
if(lump[l]!=lump[r])
{
for(int i=(lump[r]-)*block+;i<=r;i++)//暴力更新右边不完整的块
a[i]+=c;
update(lump[r]);
}
for(int i=lump[l]+;i<=lump[r]-;i++)
tag[i]+=c;
}
int binary_search(int x,int w)
{
int l=,r=ve[x].size()-;
int pos=-INF;
while(l<=r)
{
int mid=(l+r)/;
if(ve[x][mid]>=w)
{
r=mid-;
pos=r;
}
else
{
l=mid+;
pos=mid;
}
}
if(pos>=&&pos<ve[x].size()&&ve[x][pos]<w)
return ve[x][pos];
else
return INF;
}
int find(int l,int r,int c)
{
int ans=-;
for(int i=l;i<=min(lump[l]*block,r);i++)//在左边不完整的块里查找
{
if(a[i]+tag[lump[l]]<c)
ans=max(ans,a[i]+tag[lump[l]]);
}
if(lump[l]!=lump[r])
{
for(int i=(lump[r]-)*block+;i<=r;i++)//在右边的不完整的块里查找
{
if(a[i]+tag[lump[r]]<c)
ans=max(ans,a[i]+tag[lump[r]]);
}
}
for(int i=lump[l]+;i<=lump[r]-;i++)//在中间的完整的并且有序的块里二分查找
{
int t=c-tag[i];
/*int s=lower_bound(ve[i].begin(),ve[i].end(),t)-ve[i].begin();
if(s!=0&&tag[i]+ve[i][s-1]<c)
ans=max(ve[i][s-1]+tag[i],ans);*/
int s=binary_search(i,t);
if(s+tag[i]<c)
ans=max(ans,s+tag[i]);
}
return ans;
}
int main()
{
scanf("%d",&n); fill(tag,tag+maxn-,);
for(int i=;i<=n;i++)
ve[i].clear();
block=sqrt(n); for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
lump[i]=(i-)/block+;
ve[lump[i]].push_back(a[i]);
}
for(int i=;i<=lump[n];i++)//把每一块的值进行排序
sort(ve[i].begin(),ve[i].end()); for(int j=;j<=n;j++)
{
int op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==)
add(l,r,c);
else
{
int ans=find(l,r,c);
printf("%d\n",ans);
}
}
return ;
}
用set的代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 50005*2
/*struct point{
int u,w;
};
bool operator <(const point &s1,const point &s2)
{
if(s1.w!=s2.w)
return s1.w>s2.w;
else
return s1.u>s2.u;
}*/
int n,m,k,t,block;
int a[maxn],tag[maxn],lump[maxn];
set<int>se[];
void add(int l,int r,int c)
{
for(int i=l;i<=min(lump[l]*block,r);i++)//暴力更新左边不完整的块
{
se[lump[l]].erase(a[i]);
a[i]+=c;
se[lump[l]].insert(a[i]);
}
if(lump[l]!=lump[r])
{
for(int i=(lump[r]-)*block+;i<=r;i++)//暴力更新右边不完整的块
{
se[lump[r]].erase(a[i]);
a[i]+=c;
se[lump[r]].insert(a[i]);
}
}
for(int i=lump[l]+;i<=lump[r]-;i++)
tag[i]+=c;
}
int find(int l,int r,int c)
{
int ans=-;
for(int i=l;i<=min(lump[l]*block,r);i++)//在左边不完整的块里查找
{
if(a[i]+tag[lump[l]]<c)
ans=max(ans,a[i]+tag[lump[l]]);
}
if(lump[l]!=lump[r])
{
for(int i=(lump[r]-)*block+;i<=r;i++)//在右边的不完整的块里查找
{
if(a[i]+tag[lump[r]]<c)
ans=max(ans,a[i]+tag[lump[r]]);
}
}
for(int i=lump[l]+;i<=lump[r]-;i++)//在中间的完整的并且有序的块里二分查找
{
int t=c-tag[i];
set<int>::iterator it=se[i].lower_bound(t);
if(it==se[i].begin())
continue;
it--;
ans=max(ans,tag[i]+(*it));
}
return ans;
}
int main()
{
scanf("%d",&n); fill(tag,tag+maxn-,);
for(int i=;i<=;i++)
se[i].clear();
block=sqrt(n); for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
lump[i]=(i-)/block+;
se[lump[i]].insert(a[i]);
}
for(int j=;j<=n;j++)
{
int op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==)
add(l,r,c);
else
{
int ans=find(l,r,c);
printf("%d\n",ans);
}
}
return ;
}
LibreOj 6279数列分块入门 3 练习了一下set的更多相关文章
- LibreOJ 6279 数列分块入门 3(分块+排序)
题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x ...
- LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))
#6279. 数列分块入门 3 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 3 题目描述 给 ...
- loj 6278 6279 数列分块入门 2 3
参考:「分块」数列分块入门1 – 9 by hzwer 2 Description 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,询问区间内小于某个值\(x\)的元素个数. 思 ...
- LibreOJ 6277. 数列分块入门 1 题解
题目链接:https://loj.ac/problem/6277 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,单点查值. 输入格式 第一行输入一个数字 \( ...
- LibreOJ 6277 数列分块入门 1(分块)
题解:感谢hzwer学长和loj让本蒟蒻能够找到如此合适的入门题做. 这是一道非常标准的分块模板题,本来用打标记的线段树不知道要写多少行,但是分块只有这么几行,极其高妙. 代码如下: #include ...
- LibreOJ 6278. 数列分块入门 2 题解
题目链接:https://loj.ac/problem/6278 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的元素个数. ...
- LOJ 6279 数列分块入门3
嗯... 题目链接:https://loj.ac/problem/6279 这道题在分块的基础上用vc数组记录,然后最后分三块,两边暴力枚举找前驱,中间lower_bound找前驱. AC代码: #i ...
- #6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))
题目链接:https://loj.ac/problem/6279 题目大意:中文题目 具体思路:按照上一个题的模板改就行了,但是注意在整块查找的时候的下标问题. AC代码: #include<b ...
- LibreOJ 6285. 数列分块入门 9
题目链接:https://loj.ac/problem/6285 其实一看到是离线,我就想用莫队算法来做,对所有询问进行分块,但是左右边界移动的时候,不会同时更新数字最多的数,只是后面线性的扫了一遍, ...
随机推荐
- GIFDecoder源码分析
源码见:ddxxll2008/gifdecoder_java run() public void run(){ if(in != null){ readStream(); }else if(gifDa ...
- 使用Quartz框架定时发送预警邮件
1. Quartz定时发送预警邮件 1.1. 需求及实现思路 定时查询库存预警信息,一旦存在库存预警的商品,则发邮件通知相关人员 1.2. Quartz框架 Quartz是OpenSymph ...
- Mapperreduce的wordCount原理
wordcount原理: 1.mapper(Object key,Object value ,Context contex)阶段 2.从数据源读取一行数据传递给mapper函数的value 3.处理数 ...
- vue格式化显示json数据
已经是json格式数据的,直接用标签 <pre></pre>展示. 参考:https://www.jianshu.com/p/d98f58267e40
- python 网页爬虫,带登陆信息
注意点: 1. 用Fiddler抓取登陆后的headers,cookies; 2. 每抓取一次网页暂停一点时间防止反爬虫; 3. 抓取前,需要关闭Fiddler以防止端口占用. 还需解决的问题: 爬取 ...
- PT 转 PX
pt (point,磅):是一个物理长度单位,指的是72分之一英寸. px (pixel,像素):是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精度DPI(D ...
- Linux swap 使用
使用的背景 内存吃紧的时候可以考虑使用swap. swap新增 http://www.cnblogs.com/wuxie1989/p/5888595.html swap 使用 https://www. ...
- vue.js 组件引用之初级 之二
1. template 标签也可以实现替换,这样可以省去script标签了 <!DOCTYPE html> <html lang="en"> <hea ...
- Pythagorean Triples 707C
Katya studies in a fifth grade. Recently her class studied right triangles and the Pythagorean theor ...
- foreman自动化工具安装使用
简单的安装指导在官网上 官网地址为:https://theforeman.org/ 点击get started 找到 Installation 选择直接的发行版按照步骤一个一个来 需要注意的是,主机名 ...