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;elsereturn s1.u>s2.u; }*/ int n,m,k,t,block; int a[maxn],tag[maxn],lump[maxn]; vector<int>ve[510]; void update(int x) {ve[x].clear();//把第x块原来的值清除 for(int i=(x-1)*block+1;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]-1)*block+1;i<=r;i++)//暴力更新右边不完整的块a[i]+=c;update(lump[r]);}for(int i=lump[l]+1;i<=lump[r]-1;i++)tag[i]+=c;} int binary_search(int x,int w) {int l=0,r=ve[x].size()-1;int pos=-INF;while(l<=r){int mid=(l+r)/2;if(ve[x][mid]>=w){r=mid-1;pos=r;}else{l=mid+1;pos=mid;}}if(pos>=0&&pos<ve[x].size()&&ve[x][pos]<w)return ve[x][pos];elsereturn INF; } int find(int l,int r,int c) {int ans=-1;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]-1)*block+1;i<=r;i++)//在右边的不完整的块里查找 {if(a[i]+tag[lump[r]]<c)ans=max(ans,a[i]+tag[lump[r]]);} }for(int i=lump[l]+1;i<=lump[r]-1;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-1,0);for(int i=0;i<=n;i++)ve[i].clear();block=sqrt(n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);lump[i]=(i-1)/block+1;ve[lump[i]].push_back(a[i]);}for(int i=1;i<=lump[n];i++)//把每一块的值进行排序 sort(ve[i].begin(),ve[i].end());for(int j=1;j<=n;j++){int op,l,r,c;scanf("%d%d%d%d",&op,&l,&r,&c);if(op==0)add(l,r,c);else{int ans=find(l,r,c);printf("%d\n",ans);}}return 0; }
用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;elsereturn s1.u>s2.u; }*/ int n,m,k,t,block; int a[maxn],tag[maxn],lump[maxn]; set<int>se[510]; 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]-1)*block+1;i<=r;i++)//暴力更新右边不完整的块 {se[lump[r]].erase(a[i]);a[i]+=c;se[lump[r]].insert(a[i]);}}for(int i=lump[l]+1;i<=lump[r]-1;i++)tag[i]+=c;} int find(int l,int r,int c) {int ans=-1;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]-1)*block+1;i<=r;i++)//在右边的不完整的块里查找 {if(a[i]+tag[lump[r]]<c)ans=max(ans,a[i]+tag[lump[r]]);} }for(int i=lump[l]+1;i<=lump[r]-1;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-1,0);for(int i=0;i<=500;i++)se[i].clear();block=sqrt(n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);lump[i]=(i-1)/block+1;se[lump[i]].insert(a[i]);}for(int j=1;j<=n;j++){int op,l,r,c;scanf("%d%d%d%d",&op,&l,&r,&c);if(op==0)add(l,r,c);else{int ans=find(l,r,c);printf("%d\n",ans);}}return 0; }
转载于:https://www.cnblogs.com/6262369sss/p/9736601.html
LibreOj 6279数列分块入门 3 练习了一下set相关推荐
- LibreOJ 6279 数列分块入门 3(分块+排序)
题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x ...
- #6279. 数列分块入门 3(区间修改,查询权值前驱)
#6279. 数列分块入门 3 这是使用hzwer建议的set写的分块代码,set自动排序,支持二分查找,但是常数较大,比我下面写的用vector实现的分块慢了三倍,空间大了10倍. #include ...
- LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))...
#6279. 数列分块入门 3 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 3 题目描述 给出一 ...
- #6279. 数列分块入门 3
数列分块入门 3 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1000010 ...
- 「分块」数列分块入门1 – 9
ACM模板 放暑假了,回归!!! 自己不会写暴力,而且好久没写代码了,于是学学分块的优雅暴力~ 「分块入门-LibreOJ」 「分块」数列分块入门1 – 9 by hzwer 数列简单分块问题实际上有 ...
- 数列分块入门 (1 ~ 7)
分块 6277. 数列分块入门 1 分块思想 我们把每m个元素分成一块,所以我们总共的块数就是n/mn / mn/m块,一般情况下我们取m=nm = \sqrt{n}m=n.对于区间加操作,我们可以 ...
- LOJ——#6277. 数列分块入门 1
~~推荐播客~~ 「分块」数列分块入门1 – 9 by hzwer 浅谈基础根号算法--分块 博主蒟蒻,有缘人可直接观摩以上大佬的博客... #6277. 数列分块入门 1 题目大意: 给出一个长为 ...
- 【分块入门】LOJ 数列分块入门 1 - 9 (学习更新……)
dl题解 _「分块」数列分块入门1 – 9 by hzwer LOJ #6277. 数列分块入门 1 题意:给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值. 时间限制:100ms 分块 ...
- LOJ 数列分块入门6
LOJ 数列分块入门6 题目: 题目 题解: 我都不懂这题为什么要用分块... ... 直接vector就好了... 但是如果有区间修改的话就不行了.所以这题是启示我们也可以动态分块.具体就是每次插入 ...
最新文章
- springboot项目中session和cookie
- 使用element ui 日期选择器获取值后的格式问题
- emqx 使用端口_数据传输、存储、展现,EMQ X + TDengine 搭建 MQTT 物联网数据可视化平台...
- 最后一天,特邀小姐姐配音拉票,今日可投28票
- BlackBerry 应用程序开发者指南 第一卷:基础--第7章 使用数据报(Datagram)连接...
- 2月份全球制造业PMI为55.6% 已连续8个月保持在50%以上
- Java 学习多态笔记
- 码了几年代码的程序员,有一定的开发经验,应该如何提升自己?
- dell服务器运维,施用smartctl查dell服务器坏道实录
- 如何解析二维码,获取二维码里的参数供下一个接口使用
- Android之——多媒体开发视频格式
- 618省心凑背后的新算法——个性化凑单商品打包购推荐
- 天呐!惊人的Springboot测试.Springboot测试类之@RunWith注解
- C++检测键盘某键是否按下
- rosbag录制话题、播放话题多种模式
- 如何在命令行窗口运行某个文件夹下的exe程序
- SEO和反向链接对ASO的影响
- 回收站恢复的文件找不到了怎么办?竟然还有这3种靠谱的方案
- python 应用程序无法正常启动 000007b_win10打开程序提示应用程序无法正常启动提示0x000007b如何解决...
- 【应用数学】动态最优化(2):随机差分方程
热门文章
- 【Linux】一步一步学Linux——netstat命令(166)
- python中用来回溯异常的模块_python学习笔记(异常)
- int a = 0 与 int a(0) int a(b)
- Linux 下的tar常用命令及操作
- 51nod 1451 合法三角形 判斜率去重,时间复杂度O(n^2)
- Kali-linux安装之后的简单设置
- 对CAN、USART、SPI、SCI等常见总线的简单介绍
- std::mutex
- PHP+MySQL能做什么?
- php拉图片 图片变形,请大神帮我看这个图片变形公式