Codeforces 803 G. Periodic RMQ Problem
题目链接:http://codeforces.com/problemset/problem/803/G
大致就是线段树动态开节点。
然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点所代表的区间定位到原序列中,利用ST表查一下区间最小值就可以了。
定位:
llg minn(llg l,llg r)
{
if(r-l+>=n) return mt;
l%=n;if(!l) l=n;
r%=n;if(!r) r=n;
if(l>r) return min(gw(l,n),gw(,r));
else return gw(l,r);
}
其中${gw(l,r)}$表示原序列${[l,r]}$中元素的最小值。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
#define llg int
#define inf 0x7fffffff
#define maxn 500010
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg ST[maxn][],mt=inf,n,k,Q,pre[maxn],cnt; struct point
{
llg lc,rc,l,r,set,val;
}po[maxn*]; inline llg getint()
{
llg w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar(); while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} llg gw(llg l,llg r)
{
int k=pre[r-l+];
return min(ST[l][k],ST[r-(<<k)+][k]);
} llg minn(llg l,llg r)
{
if(r-l+>=n) return mt;
l%=n;if(!l) l=n;
r%=n;if(!r) r=n;
if(l>r) return min(gw(l,n),gw(,r));
else return gw(l,r);
} void make_st()
{
for(llg i=;i<=n;i++) pre[i]=pre[i>>]+;
for(llg i=;i<=n;i++) ST[i][]=getint();
for(llg i=;i<=n;i++) mt=min(mt,ST[i][]);
for(llg i=;i<=n;i++) pre[i]=pre[i>>]+;
for(llg j=;j<=;j++)
for(llg i=,u=(<<j),p=(u>>);i+u-<=n;i++)
ST[i][j]=min(ST[i][j-],ST[i+p][j-]);
cnt=,po[].l=,po[].r=n*k,po[].val=mt;
} llg new_po(llg l,llg r)
{
llg o=++cnt;
po[o].val=minn(l,r);
po[o].l=l,po[o].r=r;
return o;
} void update(llg o)
{
if (po[o].l==po[o].r) return ;
po[o].val=inf;
if (po[o].lc) po[o].val=min(po[o].val,po[po[o].lc].val);
else
{
po[o].lc=cnt+;
new_po(po[o].l,(po[o].l+po[o].r)/);
po[o].val=min(po[o].val,po[po[o].lc].val);
}
if (po[o].rc) po[o].val=min(po[o].val,po[po[o].rc].val);
else
{
po[o].rc=cnt+;
new_po((po[o].l+po[o].r)/+,po[o].r);
po[o].val=min(po[o].val,po[po[o].rc].val);
}
} void pushdown(llg o)
{
llg l=po[o].l,r=po[o].r,lc=po[o].lc,rc=po[o].rc,mid=(l+r)>>;
if (!po[o].set || l==r) return ;
if (!lc)
{
lc=cnt+;
new_po(l,mid);
}
if (!rc)
{
rc=cnt+;
new_po(mid+,r);
}
po[lc].set=po[rc].set=po[lc].val=po[rc].val=po[o].set;
po[o].set=;
po[o].lc=lc;
po[o].rc=rc;
return ;
} void modify(llg o,llg l,llg r,llg L,llg R,llg v)
{
pushdown(o);
if (o==) o=new_po(l,r);
llg mid=(l+r)>>;
if (l>=L && r<=R)
{
po[o].val=v;
po[o].set=v;
return ;
}
if (mid>=L)
{
llg son=po[o].lc;
if (po[o].lc==) po[o].lc=cnt+;
modify(son,l,mid,L,R,v);
}
if (mid<R)
{
llg son=po[o].rc;
if (po[o].rc==) po[o].rc=cnt+;
modify(son,mid+,r,L,R,v);
}
update(o);
} llg query(llg o,llg l,llg r,llg L,llg R)
{
pushdown(o);
if (o==) o=new_po(l,r);
if (l>=L && r<=R) return po[o].val;
llg mid=(l+r)>>,ans=inf;
if (mid>=L)
{
llg son=po[o].lc;
if (po[o].lc==) po[o].lc=cnt+;
ans=min(ans,query(son,l,mid,L,R));
}
if (mid<R)
{
llg son=po[o].rc;
if (po[o].rc==) po[o].rc=cnt+;
ans=min(ans,query(son,mid+,r,L,R));
}
return ans;
} int main()
{
yyj("seg");
cin>>n>>k;
make_st();
llg T=n*k;
cin>>Q;
while (Q--)
{
llg ty=getint(),l=getint(),r=getint();
if (ty==)
modify(,,T,l,r,getint());
else
printf("%d\n",query(,,T,l,r));
}
return ;
}
Codeforces 803 G. Periodic RMQ Problem的更多相关文章
- (WAWAWAWAWAWAW) G. Periodic RMQ Problem
没有联通门 : Codeforces G. Periodic RMQ Problem /* Codeforces G. Periodic RMQ Problem MMP 什么动态开点线段树啊 ... ...
- AC日记——Periodic RMQ Problem codeforces 803G
G - Periodic RMQ Problem 思路: 题目给一段序列,然后序列复制很多次: 维护序列很多次后的性质: 线段树动态开点: 来,上代码: #include <cstdio> ...
- codeforces 803G Periodic RMQ Problem
codeforces 803G Periodic RMQ Problem 题意 长度为\(1e5\)的数组复制\(1e4\)次,对新的数组进行区间覆盖和区间最小值查询两种操作,操作次数\(1e5\). ...
- Codeforces 803G Periodic RMQ Problem 线段树
Periodic RMQ Problem 动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值. 感觉有点难写.. #include<bits ...
- Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树
思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用 lazy=0 没被覆盖过 els ...
- CF803G - Periodic RMQ Problem 动态开点线段树 或 离线
CF 题意 有一个长度为n × k (<=1E9)的数组,有区间修改和区间查询最小值的操作. 思路 由于数组过大,直接做显然不行. 有两种做法,可以用动态开点版本的线段树,或者离线搞(还没搞)( ...
- BZOJ 3489: A simple rmq problem
3489: A simple rmq problem Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520[Submit] ...
- [codeforces 549]G. Happy Line
[codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...
- 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 ...
随机推荐
- linux怎么查看进程启动,用户的工作目录,pwdx,/proc/11256/cwd
linux 通过pid 寻找程序路径的最简单命令(pwdx) #pwdx pid号1 [pid2] .... 在linux实际操作命令中,查看pid的方式有很多种,通过pid找程序路径的方式也有 ...
- LigerUi之ligerMenu 右键菜单
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- vue/cli3 配置相对路径
根目录下新建 vue.config.js 文件 const path = require('path') function resolve(dir){ return path.join(__dirna ...
- Python selenium巧用Javascript脚本注入解决按钮点选问题
前段时间,笔者忙于应付公司组织的雅思考试,白天.晚上但凡有空,笔者都是埋头伏案,啃剑桥雅思(剑4~剑12)的官方模拟题或者做着与雅思考试相关的准备工作,这个过程持续了40余天.最近总算鼓起勇气走进考场 ...
- Shell脚本创建的文件夹末尾有两个问号怎么回事?
原因:Linux系统的换行符是"\r\n",Windows上的换行符是"\n",Windows上编写shell脚本上传Linux,Linux无法正确识别&quo ...
- PHP 十万数字不同数组取最大的5个 (经典面试题topK) (原)
$arr = array(3,5,7,8,1,2,456,78,...101,2345,456); 类似上述数组,共有十万个元素,让我们取出TOP5,下面是我的解法,先上代码再讲解思路 functio ...
- linux 系统管理11 ——系统安全及应用
一.基本安全措施 1.系统账号清理 (1).将非登陆用户的shell设为/sbin/nologin 方法一.usermod -s 方法二.chsh命令,交互式修改 方法三.chsh -s usermo ...
- webstorm编辑器使用
1.自动生成vue文件模板,如图
- 内存泄漏(I)
Block 解决内存泄漏 使用 weakSelf 进行解决 NSTimer 的内存泄漏与解决方案 内存泄漏
- cocos dos命令