【BZOJ】3339 RMQ Problems - Ⅰ - 题解
来源:互联网 发布:淘宝汽车冬季坐垫 编辑:程序博客网 时间:2024/06/15 15:37
【题意】
有一个长度为
【数据范围】
【分析1】30%做法:暴力
空间复杂度:
时间复杂度:
【分析2】树套树?
解决多个询问,考虑在线算法和离线算法。
先是在线算法,首先http://tieba.baidu.com/p/2813942502的算法应该错。
然后树套树应该是可以的。
但是蒟蒻并不会,所以以后应该会补充……
时间复杂度:
空间复杂度:
【分析3】60%做法:莫队算法+线段树/树状数组
考虑离线算法。区间的离线算法,想到了莫队。
用
莫队移动的过程中,维护
查找方法是从高位枚举到低位,检查权值是否满了,如果满了就用
时间复杂度:
空间复杂度:
代码:
(PS:时限是
#include <cstdio>#include <cctype>#include <cmath>#include <algorithm>using namespace std;const int N=262144;//131072*2const int MAX_BIT=20;int n,m;int a[N];int unit;struct Ques{ int l,r,id; friend inline int operator < (Ques qa,Ques qb) { return qa.l/unit!=qb.l/unit?qa.l/unit<qb.l/unit:qa.r<qb.r; }}q[N];int ans[N];int v[N];struct TreeArray{ int t[N]; inline int lowbit(int i) { return i&-i; } inline void ins(int i,int add) { for (;i<N;i+=lowbit(i)) t[i]+=add; } inline int query(void) { int now=0; for (int i=MAX_BIT;i>=0;i--) if (now+(1<<i)<N&&t[now+(1<<i)]==1<<i) now+=1<<i; return now; }}tr;inline int Read(void){ int x=0; char c=getchar(); for (;!isdigit(c);c=getchar()); for (;isdigit(c);c=getchar()) x=x*10+c-'0'; return x;}int main(void){ n=Read(),m=Read(); for (int i=1;i<=n;i++) a[i]=Read(); for (int i=1;i<=m;i++) q[i].l=Read(),q[i].r=Read(),q[i].id=i; unit=(int)sqrt(n); sort(q+1,q+m+1); int l=1,r=0; for (int i=1;i<=m;i++) { for (;l<q[i].l;l++) { v[a[l]]--; if (!v[a[l]]) tr.ins(a[l]+1,-1); } for (;l>q[i].l;l--) { v[a[l-1]]++; if (v[a[l-1]]==1) tr.ins(a[l-1]+1,1); } for (;r<q[i].r;r++) { v[a[r+1]]++; if (v[a[r+1]]==1) tr.ins(a[r+1]+1,1); } for (;r>q[i].r;r--) { v[a[r]]--; if (!v[a[r]]) tr.ins(a[r]+1,-1); } ans[q[i].id]=tr.query(); } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0;}
【分析4】100%做法:固定左端点,线段树维护每个点的
几个参考:
http://hzwer.com/3032.html
http://tieba.baidu.com/p/2813942502
这里只提实现线段树的方法有两种:①标久化标记 ②标记下传
方法①会快一些,在查询单点时只用取根到当前点路径的最小值。
时间复杂度:
空间复杂度:
代码:
/************************************************************** Problem: 1286 User: YPL Language: C++ Result: Accepted Time:236 ms Memory:54224 kb****************************************************************/#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>using namespace std;const int N=200010;const int Q=200010;const int A=200010;const int S=4000000;int n,m;int a[N];struct Ques{ int l,r,id; friend inline int operator < (Ques qa,Ques qb) { return qa.l<qb.l; }}q[Q];int ans[Q];inline int read(void){ int x=0,f=1; char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-1; for (;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;}int v[A];int nxt[N];int firSG[N],now;void Init(void){ n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i; sort(q+1,q+m+1); fill(v,v+n+1,n+1); for (int i=n;i>=1;i--) nxt[i]=v[a[i]],v[a[i]]=i; memset(v,0,sizeof v); for (int i=1;i<=n;i++) { for (v[a[i]]=1;v[now];now++); firSG[i]=now; }}struct SegmentTree{ struct TreeNode { int l,r; int mex; }tr[S]; void build(int now,int l,int r) { tr[now].l=l; tr[now].r=r; tr[now].mex=A; if (l!=r) { int mid=l+r>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); } else tr[now].mex=firSG[l]; } void ins(int now,int l,int r,int w) { if (l<=tr[now].l&&tr[now].r<=r) {tr[now].mex=min(tr[now].mex,w);return;} int mid=tr[now].l+tr[now].r>>1; if (l<=mid) ins(now<<1,l,r,w); if (mid<r) ins(now<<1|1,l,r,w); } int query(int now,int loc) { if (tr[now].l==tr[now].r) return tr[now].mex; return min(tr[now].mex,query(now<<1|loc>tr[now].l+tr[now].r>>1,loc)); }}tr;int cir=1;void Work(void){ tr.build(1,1,n); for (int i=1;i<=m;i++) { for (;cir<q[i].l;cir++) tr.ins(1,cir+1,nxt[cir]-1,a[cir]); ans[q[i].id]=tr.query(1,q[i].r); } for (int i=1;i<=m;i++) printf("%d\n",ans[i]);}int main(void){ Init(); Work(); return 0;}
【小结】
多个询问的处理维度:在线算法,离线算法
区间
[l,r] 离线处理的常见排序方法:
①按照l 排序
②按照r 排序
③分块排序
通常①②的方法效率会比③高。区间答案的处理
①区间加法
②区间减法使用方法①②,只要能搞掂一个端点的改变对所有函数值变化的一般规律即可。通常可以快速变化的函数是具有单调性的,如本题的
mex 函数。mex 函数的两个经验:
①具有单调性
②求nxt 数组
- 【BZOJ】3339 RMQ Problems - Ⅰ - 题解
- BZOJ 3339 Rmq Problem
- bzoj 3339: Rmq Problem
- 【bzoj 3339】: Rmq Problem
- bzoj 3339: Rmq Problem
- BZOJ 3339: Rmq Problem
- BZOJ 3339: Rmq Problem
- 【BZOJ】【P3339&P3585】【Rmq Problem/mex】【题解】【离线】
- BZOJ 3339: Rmq Problem 莫队水题
- BZOJ 3339: Rmq Problem|莫队算法
- bzoj 3339: Rmq Problem(线段树)
- bzoj 3339 Rmq problem 离线+线段树
- BZOJ 3585/3339 mex/Rmq Problem 莫队
- bzoj题解
- BZOJ 3339/3585 Rmq Problem/mex 莫队算法
- BZOJ 3339 Rmq Problem【离线,值域线段树
- BZOJ 3339: Rmq Problem 穿了棉袄的线段树
- BZOJ 1067 RMQ+认真审题
- webrtct: talky, OTALK,web4 基于webrtc的 即使通讯 开源代码!
- Hdu 1233 还是畅通工程
- 引—新的开始
- Mobile architecture
- Android通知的使用及简单二次封装
- 【BZOJ】3339 RMQ Problems - Ⅰ - 题解
- Javascript学习笔记之类与继承(一)
- 秒杀系统架构分析与实战
- poj 2528 Mayor's posters 线段树
- win 命令行常用命令
- Android 代码混淆 选项说明
- AS关于buildToolVersion与CompileSdkVersion的区别
- CodeForces 590B Chip 'n Dale Rescue Rangers 题解
- 合并静态库总结