CF803G Periodic RMQ Problem
简要题意
你需要维护一个序列 \(a\),有 \(q\) 个操作,支持:
1 l r x将 \([l,r]\) 赋值为 \(x\)。2 l r询问 \([l,r]\) 的最小值。
为了加大难度,\(a\) 不会直接告诉你,但是会告诉你一个长度为 \(n\) 的序列 \(b\) 和一个整数 \(k\),\(a\) 是将 \(b\) 复制 \(k\) 遍依次拼接而成。
\(1 \leq n,q \leq 10^{5},1 \leq k \leq 10^{4},1 \leq b_i \leq 10^9,1 \leq l_i \leq r_i \leq nk\)
思路
如果直接求出 \(a\),那么时间复杂度和空间复杂度(都是 \(O(nk)\))不能接受。
我发现,如果没有修改,那么只需要用一个 ST 表即可,具体操作如下:
- 如果 \((r-l+1)\geq n\),那么一定包含所有 \(b\) 中的元素,直接返回 \(b[1,n]\) 的最小值。
- 如果 \((l-1)\bmod n+1>(r-1)\bmod n+1\),那么这个区间是跨区块的,如图:

(红色为 \(b\) 块,蓝色为询问 \([l,r]\),黑色为数值)
那么就是相对应的后缀最小值和前缀最小值的最小值。
- 剩下的情况是完全在 \(b\) 块中,ST 表查询。
如果带上修改呢?我们可以打一个标记,如果这个区间有修改,那么直接读取修改后的结果,否则走上述过程。这一步可以使用动态开点线段树完成。
不过我的动态开点线段树总是会 TLE 掉一些点,由于本题数据随机,我们使用 ODT 替换掉动态开点线段树,就可以 AC 了。
时间复杂度均摊 \(O(n\log n+q\log nk)\),可以通过本题。
代码
#include<bits/stdc++.h>
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
using namespace std;
const int N=100005;
int n,m,k,f[N][25],lg[N]= {-1},pre[N],suf[N];
int min_=INT_MAX,min_ans=INT_MAX;
int st(int l,int r){
int logg=lg[r-l+1];
return min(f[l][logg],f[r-(1<<logg)+1][logg]);
}
int solve(int l,int r) {
if(r-l+1>=n){// 如果包含整个块,那么最小值一定是 min(b[1],...,b[n])
return min_;
}
l=(l-1)%n+1; // 转成块内坐标
r=(r-1)%n+1;// 转成块内坐标
if(l>r){// 如果不在同一个块,直接返回右半块+左半块
return min(pre[r],suf[l]);
}
return st(l,r); // 如果在同一个块,ST表查询
}
struct node {
int l,r;
mutable int v;
bool covered;
node(int ls,int rs=-1,int vv=0,bool coverevd=0){
l=ls,r=rs,v=vv,covered=coverevd;
}
bool operator<(const node &a)const {
return this->l<a.l;
}
};
set<node>s;
set<node>::iterator split(int p) {// 分裂区间
if(p>n*k)return s.end();
set<node>::iterator it=--s.upper_bound(node(p,0,0,0));
if((*it).l==p)return it;
int l=(*it).l,r=(*it).r,v=(*it).v;
bool covered=(*it).covered;
s.erase(it);
s.insert(node(l,p-1,v,covered));
return s.insert(node(p,r,v,covered)).first;
}
void assign(int l,int r,int v) { // 区间赋值
set<node>::iterator rs=split(r+1),ls=split(l);
s.erase(ls,rs);
s.insert(node(l,r,v,1));
min_ans=min(min_ans,v);
}
int query(int l,int r) {
int ans=INT_MAX;
set<node>::iterator rs=split(r+1),ls=split(l);
for(set<node>::iterator it=ls; it!=rs; ++it) {
bool covered=(*it).covered;
if(covered) { // 如果被覆盖了,就直接用覆盖的值
ans=min(ans,(*it).v);
} else { // 如果没有被覆盖,就去 ST 表中查询
ans=min(ans,solve((*it).l,(*it).r));
}
if(ans==min_ans)break; // 如果已经查到全序列最小值,就直接返回
}
return ans;
}
int main() {
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) {
scanf("%d",&f[i][0]);
}
pre[0]=suf[n+1]=INT_MAX;
for(int i=1;i<=n;i++) {
pre[i]=min(pre[i-1],f[i][0]);
lg[i]=lg[i>>1]+1;
min_=min(min_,f[i][0]);
min_ans=min(min_ans,f[i][0]);
}
for(int i=n;i>=1;i--) {
suf[i]=min(suf[i+1],f[i][0]);
}
for(int j=1;j<=20;j++) {
for(int i=1;i<=n+1-(1<<j);i++){
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
s.insert(node(1,n*k,min_,0));
scanf("%d",&m);
for(int i=1;i<=m;i++) {
int op,l,r,x;
scanf("%d%d%d",&op,&l,&r);
if(op==1) {
scanf("%d",&x);
assign(l,r,x);
} else {
printf("%d\n",query(l,r));
}
}
return 0;
}
CF803G Periodic RMQ Problem的更多相关文章
- CF803G - Periodic RMQ Problem 动态开点线段树 或 离线
CF 题意 有一个长度为n × k (<=1E9)的数组,有区间修改和区间查询最小值的操作. 思路 由于数组过大,直接做显然不行. 有两种做法,可以用动态开点版本的线段树,或者离线搞(还没搞)( ...
- Codeforces 803G Periodic RMQ Problem 线段树
Periodic RMQ Problem 动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值. 感觉有点难写.. #include<bits ...
- codeforces 803G Periodic RMQ Problem
codeforces 803G Periodic RMQ Problem 题意 长度为\(1e5\)的数组复制\(1e4\)次,对新的数组进行区间覆盖和区间最小值查询两种操作,操作次数\(1e5\). ...
- AC日记——Periodic RMQ Problem codeforces 803G
G - Periodic RMQ Problem 思路: 题目给一段序列,然后序列复制很多次: 维护序列很多次后的性质: 线段树动态开点: 来,上代码: #include <cstdio> ...
- (WAWAWAWAWAWAW) G. Periodic RMQ Problem
没有联通门 : Codeforces G. Periodic RMQ Problem /* Codeforces G. Periodic RMQ Problem MMP 什么动态开点线段树啊 ... ...
- Codeforces 803 G. Periodic RMQ Problem
题目链接:http://codeforces.com/problemset/problem/803/G 大致就是线段树动态开节点. 然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点 ...
- Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树
思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用 lazy=0 没被覆盖过 els ...
- BZOJ 3489: A simple rmq problem
3489: A simple rmq problem Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520[Submit] ...
- BZOJ3339 Rmq Problem
[bzoj3339]Rmq Problem Description Input Output Sample Input 7 5 0 2 1 0 1 3 2 1 3 2 3 1 4 3 6 2 7 Sa ...
- bzoj 3489: A simple rmq problem k-d树思想大暴力
3489: A simple rmq problem Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 551 Solved: 170[Submit][ ...
随机推荐
- laravel 浏览器谷歌network返回报错html
laravel 在谷歌报错的时候会返回html,对于调试来说很不方便.原因是在于: 这里返回的格式是json,但是报错时候返回的是整个html所以 相对路径: app\Exceptions\Handl ...
- nginx 通过IP访问项目
项目新需求,因为是小范围使用的网站,所以不打算配域名,直接通过IP访问当前项目. 环境: LNMP 一键集成环境 当前IP指向的目录 :/home/wwwroot/default/ 但是我的项目.需要 ...
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(29)-Fiddler如何抓取Android7.0以上的Https包-终篇
1.简介 上一篇宏哥介绍的Xposed是一款可以在不修改APK的情况下影响程序运行的框架.可以编写并加载自己编写的插件app,实现对目标apk的注入.拦截等.一般研究移动安全的都会使用Xposed. ...
- SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截
项目依赖 SpringBoot 2.5.5 SpringCloud 2020.0.4 Alibaba Spring Cloud 2021.1 Mybatis Plus 3.4.0 Seata 1.4. ...
- AIR32F103(三) Linux环境基于标准外设库的项目模板
目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...
- Arctic 基于 Hive 的流批一体实践
背景 随着大数据业务的发展,基于 Hive 的数仓体系逐渐难以满足日益增长的业务需求,一方面已有很大体量的用户,但是在实时性,功能性上严重缺失:另一方面 Hudi,Iceberg 这类系统在事务性,快 ...
- uni-app 配置MuMu手机模拟器 (2022-2-24)
(1)到官网"https://mumu.163.com/"下载,我选中的中间的那个 (2)下载完成后,默认安装即可,直接等待安装完成 (3)在uni-app里设置端口,在uni-a ...
- ATT&CK框架整理(中英文整理)
工作需要了解了一下ATT&CK框架,留个记录.
- 独立按键控制led灯
#include "regx51.h"typedef unsigned int u16; void delay_us(u16 time){ while(time--){} }voi ...
- 前端html和css总结
1.html知识总结 1.1 表格的的相关属性 属性 表示 border-collapse 设置表格的边框是否被合并为一个单一的边框 cellpadding 单元格边距 cellspacing 单元格 ...