POJ_3368_Frequent values_线段树/ST稀疏表
来源:互联网 发布:sequoiadb巨杉数据库 编辑:程序博客网 时间:2024/05/20 06:06
头疼
题意
给一个n长度的a int数组,且a数组为不下降数列,询问q次,每次询问l到r之间出现次数最多的数字出现了多少次。
IO
Input
The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , … , an (-100000 ≤ ai ≤ 100000, for each i ∈ {1, …, n}) separated by spaces. You can assume that for each i ∈ {1, …, n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the
query.
The last test case is followed by a line containing a single 0.
Output
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
分析
一开始一看这题询问区间内值的分布情况,就想用主席树,结果到了询问的时候仔细想想又发现主席树破不了。
总是出现这样的问题就是过于注重分析如何维护数据结构保持consistant,而不认真地想想数据结构维护什么数据才能得到答案。
这题把问题转化成了RMQ问题,计算每个数值出现的次数,然后把这个数组按照数字出现的顺序排成一个新的数组,并且记录原数组中每个位置对应新数组中哪个位置,记录新数组每个数对应原数组的区间范围,由于是不下降数列,这些很自然。
然后线段树或者ST稀疏表维护RMQ信息,对于一次查询l,r,先修改l和r对应新数组位置的值,因为可能正好卡在一串相等数字的中间,然后查询对应区间的RMQ信息,再把信息改回来。
还有另一种办法是比较l位置和l位置值结束位置、r位置和r位置值开始位置、l值结束位置和r值开始位置之间的RMQ信息,这样就不需要更新操作。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define MXN 100010int da[MXN];int n,q;int a[MXN],st[MXN],ed[MXN],mp[MXN];int cnt;int ll[MXN<<2],rr[MXN<<2],mx[MXN<<2];void build(int id,int l,int r){ ll[id]=l,rr[id]=r; if(l==r){ mx[id]=da[l]; return; } int m=(l+r)>>1,ls=id<<1,rs=ls|1; build(ls,l,m); build(rs,m+1,r); mx[id]=max(mx[ls],mx[rs]);}void update(int id,int loc,int num){ if(ll[id]==rr[id]){ mx[id]=num; return; } int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1; if(loc<=m) update(ls,loc,num); else update(rs,loc,num); mx[id]=max(mx[ls],mx[rs]);}int query(int id,int l,int r){ if(ll[id]==l&&rr[id]==r) return mx[id]; int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1; if(r<=m) return query(ls,l,r); else if(l>m) return query(rs,l,r); else return max(query(ls,l,m),query(rs,m+1,r));}int main(){ while(scanf("%d",&n)!=EOF&&n){ scanf("%d",&q); cnt=-1; int pre=-1000000; for(int i=1;i<=n;++i){ scanf("%d",a+i); if(a[i]!=pre){ if(pre!=-1000000){ ed[cnt]=i-1; } ++cnt; da[cnt]=0; st[cnt]=i; pre=a[i]; } mp[i]=cnt; ++da[cnt]; } ++cnt; build(1,0,cnt-1); for(int Q=0;Q<q;++Q){ int l,r; scanf("%d%d",&l,&r); int tl=mp[l],tr=mp[r]; if(tl==tr){ printf("%d\n",r-l+1); continue; } update(1,tl,ed[tl]-l+1); update(1,tr,r-st[tr]+1); printf("%d\n",query(1,tl,tr)); update(1,tl,ed[tl]-st[tl]+1); update(1,tr,ed[tr]-st[tr]+1); } } return 0;}
- POJ_3368_Frequent values_线段树/ST稀疏表
- POJ_3368_Frequent values_线段树
- POJ3368_Frequent values_线段树
- poj 3368_Frequent values_线段树
- ST 稀疏表
- ST(稀疏表)算法
- 【模板】ST稀疏表
- ST(稀疏表)算法
- POJ3264 Balanced Lineup 线段树|ST表
- nyoj1068 ST 线段树
- RMQ问题 (st+线段树)
- POJ 3264 线段树 ST
- [Noi2010] D1T2 超级钢琴 (ST表 线段树 主席树)
- Balanced Lineup-POJ - 3264-RMQ线段树/st表
- Codevs 4373 窗口(线段树 单调队列 st表)
- csu1798: 小Z的城市 线段树+ST表
- HDU 5875 Function 线段树 || (ST表 + 二分)
- HDU 5875 Function (ST表+二分 or 线段树)
- 时间加减运用派生和重载
- 使用GitHub和Hexo搭建免费静态Blog
- css技巧总结
- CPP链表实现栈
- java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.FilterDispatcher
- POJ_3368_Frequent values_线段树/ST稀疏表
- CreateRemoteThread
- 读json文件
- Android 网络管理
- hdu 1298 T9 字典树+DFS
- jQuery与javascript方法比较
- python之一些细节
- 编写高质量IOS代码(二)
- 登录加密测验