Rmq Problem
来源:互联网 发布:cydia软件源 big 编辑:程序博客网 时间:2024/06/14 18:21
Rmq Problem
主席树 or 线段树
3339: Rmq Problem
题解:
一、主席树:
我们考虑建权值线段树,每个数字 x 保存它最后出现的位置
这样查询[l,r],就是找第r棵主席树中第一个值 < l 的
主席树上每个区间维护当前数中,权值从 l 到 r 中最后一次出现最靠左的位置
就是相当于维护区间最小值即可
Code:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 200000*20;const int MX_A = 200001;int n,q;int lch[N],rch[N],mn[N],root[N],sz;void clone(int t,int p){ lch[t]=lch[p]; rch[t]=rch[p]; mn[t]=mn[p];}void insert(int &t,int p,int l,int r,int x,int d){ t=++sz; clone(t,p); if(l!=r){ int mid=(l+r)>>1; if(x<=mid) insert(lch[t],lch[p],l,mid,x,d); else insert(rch[t],rch[p],mid+1,r,x,d); mn[t]=min(mn[lch[t]],mn[rch[t]]); } else{ mn[t]=d; }}int query(int t,int l,int r,int ql){ if(l==r) return l; int mid=(l+r)>>1; if(mn[lch[t]]<ql) return query(lch[t],l,mid,ql); else return query(rch[t],mid+1,r,ql);}int main(){ freopen("a.in","r",stdin); scanf("%d%d",&n,&q); int a; for(int i=1;i<=n;i++){ scanf("%d",&a); a++; insert(root[i],root[i-1],1,MX_A,a,i); } int l,r; while(q--){ scanf("%d%d",&l,&r); printf("%d\n",query(root[r],1,MX_A,l)-1); }}
二、线段树:
(抄的黄学长的)
首先按照左端点将询问排序
然后一般可以这样考虑
首先如何得到1-i的sg值呢
这个可以一开始扫一遍完成
接着考虑l-r和l+1-r的答案有何不同
显然是l-next[l]-1这一段所有sg值大于a[l]的变为a[l]
这一步如果暴力修改的话只有30分
但是修改区间我们可以想到线段树,这样就能a了
Code:
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define D(x) cout<<#x<<" = "<<x<<" "#define E cout<<endlconst int INF = 0x3f3f3f3f;const int NO_TAG = INF;const int N = 200005;using namespace std;int sg[N],mark[N],n,m,a[N],next[N],last[N];struct Data{ int l,r,id,ans;} q[N];bool cmp_l(const Data &a, const Data &b){ return a.l < b.l;}bool cmp_id(const Data &a, const Data &b){ return a.id < b.id;}struct Node{ int l,r,tag;} pool[N*4];void pushdown(int x){ Node &t=pool[x]; if(t.tag!=NO_TAG){ pool[x*2].tag=min(pool[x*2].tag,t.tag); pool[x*2+1].tag=min(pool[x*2+1].tag,t.tag); t.tag=NO_TAG; }}void build(int x,int l,int r){ Node &t=pool[x]; t.l=l; t.r=r; t.tag=NO_TAG; if(l!=r){ int mid=(t.l+t.r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); } else{ t.tag=sg[l]; }}void setMin(int x,int ql,int qr,int d){ Node &t=pool[x]; if(ql<=t.l && t.r<=qr){ t.tag=min(t.tag,d); } else{ int mid=(t.l+t.r)>>1; if(ql<=mid) setMin(x*2,ql,qr,d); if(qr>mid) setMin(x*2+1,ql,qr,d); }}int query(int x,int p){// D(x); D(p); Node &t=pool[x]; if(t.l==t.r) return t.tag; else{ pushdown(x); int mid=(t.l+t.r)>>1; if(p<=mid) return query(x*2,p); else return query(x*2+1,p); }}int main(){ freopen("a.in","r",stdin); scanf("%d%d",&n,&m); int mex=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); mark[a[i]]++; if(a[i]==mex){ while(mark[mex]) mex++; } sg[i]=mex;// D(sg[i]); E; } build(1,1,n); for(int i=n;i>=1;i--){ next[i]=last[a[i]]==0?n+1:last[a[i]]; last[a[i]]=i;// D(next[i]); E; } for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+1+m,cmp_l); int now=1; for(int i=1;i<=m;i++){ while(now<q[i].l){ setMin(1,now,next[now]-1,a[now]); now++; } q[i].ans=query(1,q[i].r);// D(q[i].l); D(q[i].r); D(q[i].ans); E; } sort(q+1,q+1+m,cmp_id); for(int i=1;i<=m;i++){ printf("%d\n",q[i].ans); }}
阅读全文
0 0
- Rmq Problem
- BZOJ 3339 Rmq Problem
- bzoj 3339: Rmq Problem
- 【bzoj 3339】: Rmq Problem
- 【bzoj3339】Rmq Problem
- 【BZOJ3339】Rmq Problem
- bzoj3339 Rmq Problem
- bzoj 3339: Rmq Problem
- BZOJ 3339: Rmq Problem
- Codeforces803G Periodic RMQ Problem
- 【bzoj3339】Rmq Problem
- BZOJ 3339: Rmq Problem
- RMQ Problem.md
- bzoj3339: Rmq Problem
- poj 2452 RMQ(Sticks Problem)
- hdu 5443 water problem (RMQ)
- The Water Problem(RMQ)
- [BZOJ3339] Rmq Problem&&[BZOJ3585] mex
- 前台用ajax向springMvc传数组
- 七月份的最后一天
- 埋点统计自定义上报
- 【Oracle】记一次数据库连接没有关闭导致数据库宕机的排查过程
- mark 一下node-glob 语法
- Rmq Problem
- 关于移动端布局
- 创建搜索二叉树
- HDU 5128 The E-pang Palace(暴力)
- 7月31日掉坑记录
- Linux常用操作命令记录(持续更新)
- ASP.NET Web Forms 转换至MVC开发
- 实现C中的strcpy函数
- APP功能测试要点