题目链接: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相关推荐

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

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

  2. #6279. 数列分块入门 3(区间修改,查询权值前驱)

    #6279. 数列分块入门 3 这是使用hzwer建议的set写的分块代码,set自动排序,支持二分查找,但是常数较大,比我下面写的用vector实现的分块慢了三倍,空间大了10倍. #include ...

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

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

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

    数列分块入门 3 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1000010 ...

  5. 「分块」数列分块入门1 – 9

    ACM模板 放暑假了,回归!!! 自己不会写暴力,而且好久没写代码了,于是学学分块的优雅暴力~ 「分块入门-LibreOJ」 「分块」数列分块入门1 – 9 by hzwer 数列简单分块问题实际上有 ...

  6. 数列分块入门 (1 ~ 7)

    分块 6277. 数列分块入门 1 分块思想 我们把每m个元素分成一块,所以我们总共的块数就是n/mn / mn/m块,一般情况下我们取m=nm = \sqrt{n}m=n​.对于区间加操作,我们可以 ...

  7. LOJ——#6277. 数列分块入门 1

    ~~推荐播客~~ 「分块」数列分块入门1 – 9 by hzwer 浅谈基础根号算法--分块 博主蒟蒻,有缘人可直接观摩以上大佬的博客... #6277. 数列分块入门 1 题目大意: 给出一个长为 ...

  8. 【分块入门】LOJ 数列分块入门 1 - 9 (学习更新……)

    dl题解 _「分块」数列分块入门1 – 9 by hzwer LOJ #6277. 数列分块入门 1 题意:给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值. 时间限制:100ms 分块 ...

  9. LOJ 数列分块入门6

    LOJ 数列分块入门6 题目: 题目 题解: 我都不懂这题为什么要用分块... ... 直接vector就好了... 但是如果有区间修改的话就不行了.所以这题是启示我们也可以动态分块.具体就是每次插入 ...

最新文章

  1. springboot项目中session和cookie
  2. 使用element ui 日期选择器获取值后的格式问题
  3. emqx 使用端口_数据传输、存储、展现,EMQ X + TDengine 搭建 MQTT 物联网数据可视化平台...
  4. 最后一天,特邀小姐姐配音拉票,今日可投28票
  5. BlackBerry 应用程序开发者指南 第一卷:基础--第7章 使用数据报(Datagram)连接...
  6. 2月份全球制造业PMI为55.6% 已连续8个月保持在50%以上
  7. Java 学习多态笔记
  8. 码了几年代码的程序员,有一定的开发经验,应该如何提升自己?
  9. dell服务器运维,施用smartctl查dell服务器坏道实录
  10. 如何解析二维码,获取二维码里的参数供下一个接口使用
  11. Android之——多媒体开发视频格式
  12. 618省心凑背后的新算法——个性化凑单商品打包购推荐
  13. 天呐!惊人的Springboot测试.Springboot测试类之@RunWith注解
  14. C++检测键盘某键是否按下
  15. rosbag录制话题、播放话题多种模式
  16. 如何在命令行窗口运行某个文件夹下的exe程序
  17. SEO和反向链接对ASO的影响
  18. 回收站恢复的文件找不到了怎么办?竟然还有这3种靠谱的方案
  19. python 应用程序无法正常启动 000007b_win10打开程序提示应用程序无法正常启动提示0x000007b如何解决...
  20. 【应用数学】动态最优化(2):随机差分方程

热门文章

  1. 【Linux】一步一步学Linux——netstat命令(166)
  2. python中用来回溯异常的模块_python学习笔记(异常)
  3. int a = 0 与 int a(0) int a(b)
  4. Linux 下的tar常用命令及操作
  5. 51nod 1451 合法三角形 判斜率去重,时间复杂度O(n^2)
  6. Kali-linux安装之后的简单设置
  7. 对CAN、USART、SPI、SCI等常见总线的简单介绍
  8. std::mutex
  9. PHP+MySQL能做什么?
  10. php拉图片 图片变形,请大神帮我看这个图片变形公式