POJ 3368.Frequent values(RMQ和线段树)
2015-07-27 14:44
441 查看
2015-06-10
问题简述:
输入一个非递减的数组,输出其中下标 i 到 j 中最大连续元素的个数。
原题链接:http://poj.org/problem?id=3368
解题思路:
由于数组长度和查询次数过大,使用遍历算法暴力求解必然导致 TLE,所以我们要另想方法。这里可以使用 RMQ问题中的ST算法或线段树 来优化问题解决的时间复杂度。
方法一:ST算法,即 Sparse Table 算法。它的时间复杂度为<O(nlogn), O(1)>,即预处理为 O(nlogn),而查询仅需O(1)的时间。
本文提供有关该算法的讲稿,链接: http://pan.baidu.com/s/1hqCg17I 密码: d3m3。
方法二:线段树。线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。本题使用线段树存储区间最大值,使得查询时间复杂度降为 O(logn)。
具体操作:使用一个数组 cnt 记录每一个数依次出现的次数,然后使用上述两个算法对这个数组进行操作,使利于查询。为了便于查找原数组下标,还要建立一个数据结构保存 cnt 对应的数的最小下标和最大下标以及 cnt 的下标。
源代码:
ST算法:
线段树:
问题简述:
输入一个非递减的数组,输出其中下标 i 到 j 中最大连续元素的个数。
原题链接:http://poj.org/problem?id=3368
解题思路:
由于数组长度和查询次数过大,使用遍历算法暴力求解必然导致 TLE,所以我们要另想方法。这里可以使用 RMQ问题中的ST算法或线段树 来优化问题解决的时间复杂度。
方法一:ST算法,即 Sparse Table 算法。它的时间复杂度为<O(nlogn), O(1)>,即预处理为 O(nlogn),而查询仅需O(1)的时间。
本文提供有关该算法的讲稿,链接: http://pan.baidu.com/s/1hqCg17I 密码: d3m3。
方法二:线段树。线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。本题使用线段树存储区间最大值,使得查询时间复杂度降为 O(logn)。
具体操作:使用一个数组 cnt 记录每一个数依次出现的次数,然后使用上述两个算法对这个数组进行操作,使利于查询。为了便于查找原数组下标,还要建立一个数据结构保存 cnt 对应的数的最小下标和最大下标以及 cnt 的下标。
源代码:
ST算法:
/* OJ: POJ ID: 3013216109 TASK: 3368.Frequent values LANG: C++ NOTE: RMQ(ST算法) */ #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int MAX=100005; int a[MAX],dp[MAX][18]; int cnt[MAX]; struct trip { int s,e; int num; }wap[MAX]; int main() { int n,q,x,y,i,j; while(scanf("%d",&n),n) { scanf("%d",&q); memset(wap,0,sizeof(wap)); memset(cnt,0,sizeof(cnt)); int k=1; scanf("%d",&a[1]); wap[k].s=1; for(i=2;i<=n;i++) { scanf("%d",&a[i]); if(a[i]==a[i-1]) { cnt[k]++; //wap[k].e=i; wap[i].s=wap[i-1].s; } else { cnt[k]++; wap[i].e=i-1; k++; wap[i].s=i; } } wap[n+1].e=n; cnt[k]++; for(i=1,j=1;i<=n;) { for(int f=i;f<i+cnt[j];f++) wap[f].num=j; for(int f=i+1;f<i+cnt[j];f++) wap[f].s=wap[f-1].s; for(int f=i+cnt[j]-1;f>=i;f--) wap[f].e=wap[f+1].e; i+=cnt[j];j++; } int f; for(f=17;f>=0;f--) if((1<<f)<=k) break; f++; int p=floor(log((double)(n+1))/log(2.0)); for(i=1;i<=k;i++) dp[i][0]=cnt[i]; for(j=1;j<=p;j++) for(i=1;i+(1<<j)-1<=k;i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); while(q--) { scanf("%d %d",&x,&y); int i,st,rt,ans; st=wap[x].num; rt=wap[y].num; if((rt-st)==0) ans=y-x+1; else if((rt-st)==1) ans=max(wap[x].e-x+1,y-wap[y].s+1); else { int p=floor((log((double)(rt-st-1))/log(2.0))); ans=max(dp[st+1][p],dp[rt-(1<<p)][p]); ans=max(wap[x].e-x+1,ans); ans=max(ans,y-wap[y].s+1); } printf("%d\n",ans); } } return 0; }
线段树:
/* OJ: POJ ID: 3013216109 TASK: 3368.Frequent values LANG: C++ NOTE: 线段树 */ #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int MAX=100005; int a[MAX],dp[MAX][18]; int cnt[MAX],tree[MAX*4],f; struct trip { int s,e; int num; }wap[MAX]; void build(int l,int r,int flag) { if(l==r) { tree[flag]=cnt[f++]; return; } int m=(l+r)/2; build(l,m,flag*2); build(m+1,r,flag*2+1); tree[flag]=max(tree[flag<<1],tree[flag<<1|1]); } int query(int x,int y,int l,int r,int flag) { if(x<=l&&r<=y) return tree[flag]; int m=(l+r)/2; int ans=0; if(x<=m) ans=max(ans,query(x,y,l,m,flag<<1)); if(y>m) ans=max(ans,query(x,y,m+1,r,flag<<1|1)); return ans; } int main() { int n,q,x,y,i,j; while(scanf("%d",&n),n) { scanf("%d",&q); memset(wap,0,sizeof(wap)); memset(cnt,0,sizeof(cnt)); int k=1; scanf("%d",&a[1]); wap[k].s=1; for(i=2;i<=n;i++) { scanf("%d",&a[i]); if(a[i]==a[i-1]) { cnt[k]++; wap[i].s=wap[i-1].s; } else { cnt[k]++; wap[i].e=i-1; k++; wap[i].s=i; } } wap[n+1].e=n; cnt[k]++; for(i=1,j=1;i<=n;) { for(int f=i;f<i+cnt[j];f++) wap[f].num=j; for(int f=i+1;f<i+cnt[j];f++) wap[f].s=wap[f-1].s; for(int f=i+cnt[j]-1;f>=i;f--) wap[f].e=wap[f+1].e; i+=cnt[j];j++; } f=1; build(1,k,1); while(q--) { scanf("%d %d",&x,&y); int i,st,rt,ans; st=wap[x].num; rt=wap[y].num; if((rt-st)==0) ans=y-x+1; else if((rt-st)==1) ans=max(wap[x].e-x+1,y-wap[y].s+1); else { ans=query(st+1,rt-1,1,k,1); ans=max(wap[x].e-x+1,ans); ans=max(ans,y-wap[y].s+1); } printf("%d\n",ans); } } return 0; }
相关文章推荐
- POJ 2442.Sequence
- UITextfield设置Placeholder颜色 控件 内边距、自适应高度
- 自动获取UILabel的宽度高度
- 2.1-特殊权限之guid
- 2.0-特殊权限之suid
- Android开发规范(编码+性能+UI)
- iOS UITableView的使用 (选自oschina)
- The Unique MST----poj1679次小生成树
- poj 1679 The Unique MST
- ${pageContext.request.contextPath}和request.contextPath的区别 分类: jsp el表达式 2013-07-17 15:50 7184人阅读 评论
- [SoapUI] SOAP UI-Groovy Useful Commands
- Xcode6 storyboard new push segue 后的视图控制器没有navigation item bug.
- iOS UIStatusBar字体颜色及隐藏动画
- managedQuery过时的解决办法
- Hibernate 连接数据库,取出query.list()集合中的元素
- [单调队列] hdu 3415 Max Sum of Max-K-sub-sequence
- hdu 5312 Sequence
- iOS Human Interface Guidelines(原创翻译)第四章
- 【线段树】spoj GSS2 Can you answer these queries II
- HDU5312.Sequence