UVA 11235 Frequent values 线段树/RMQ
vjudge 上题目链接:UVA 11235
*******************************************************大白书上解释************************************************************
题目大意:给出一个非降序排列的整数数组 a1,a2,a3,...,an,你的任务是对于一系列询问 (i, j),回答 ai,ai+1,...,aj 中出现次数最多的值所出现的次数。
输入格式:包含多组数据。每组数据第一行为两个整数 n 和 q(1 <= n, q <= 100000)。第二行包含 n 个非降序排列的整数 a1,a2,a3,...,an(-100000 <= ai <= 100000)。以下 q 行每行包含两个整数 i 和 j(1 <= i <= j <= n),输入结束标志为 n = 0。
输出格式:对于每个查询,输出查询结果。
分析:应注意到整个数组是非降序的,所有相等元素都会聚集到一起。这样就可以把整个数组进行游程编码(Run Length Encoding, RLE)。比如 -1,1,1,2,2,2,4 就可以编码成 (-1, 1), (1, 2), (2, 3), (4, 1),其中 (a, b) 表示有 b 个连续的 a。用 value[i] 和 count[i] 分别表示第 i 段的数值和出现次数,num[p], left[p], right[p] 分别表示位置 p 所在段的编号和左右端点位置,则在下图的情况,每次查询(L,R)的结果为以下 3 个部分的最大值:从 L 到 L 所在段的结束处的元素个数(即 right[L] - L + 1)、从 R 所在段的开始处到 R 处的元素个数(即 R - left[R] + 1)、中间第 num[L] + 1 段到第 num[R] - 1 段的 count 的最大值,如图 3-8 所示。

*******************************************************大白书上解释结束************************************************************
我的理解:
预处理过程主要就 3 个数组:seq[] 就是上述提到的 count[] 数组,记录 seq[i] 第 i 段连续整数的出现次数;pos[i] 表示原数组的第 i 个元素在 seq[] 中处于第几段;preSum[] 则是 seq 数组的前缀和,用于快速求出第 L 段和第 R 段的元素个数。这 3 个数组准备好后,接下来就是求区间最值的问题而已,线段树或者 RMQ 都可以,二者复杂度一样,时间差异可以忽略不计,只不过我更熟悉线段树,感觉 RMQ 的边界有点不容易处理而已。
首先是线段树的代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
#define For(i,s,t) for(int i = (s); i < (t); ++i)
#define root int rt, int l, int r
#define ll(rt) ((rt) << 1)
#define rr(rt) (ll(rt) | 1)
#define makemid int mid = (l + r >> 1)
#define lson ll(rt), l, mid
#define rson rr(rt), mid + 1, r
const int N = ; int c[N];
vector<int> seq, preSum;
int pos[N] = {,}; int Max[N << ]; inline void pushup(int rt) { Max[rt] = max(Max[ll(rt)], Max[rr(rt)]); } void build(root)
{
if(l == r) {
Max[rt] = seq[l - ];
return;
}
makemid;
build(lson);
build(rson);
pushup(rt);
} int ql, qr;
int query(root)
{
if(ql <= l && r <= qr) {
return Max[rt];
}
makemid;
int ret = ;
if(ql <= mid) {
ret = max(ret, query(lson));
}
if(qr > mid) {
ret = max(ret, query(rson));
}
return ret;
} int main()
{
int n,q;
while(~scanf("%d",&n), n) {
scanf("%d", &q);
seq.clear();
scanf("%d", c);
int curValue = c[], curNum = ;
For(i, , n) {
scanf("%d", c + i);
if(c[i] == curValue) {
++curNum;
pos[i] = pos[i - ];
} else {
seq.push_back(curNum);
curValue = c[i];
curNum = ;
pos[i] = pos[i - ] + ;
}
}
seq.push_back(curNum);
preSum.clear();
preSum.push_back(seq[]);
int len = seq.size();
For(i, , len) {
preSum.push_back(preSum[i - ] + seq[i]);
}
build(, , len);
int x,y;
while(q--) {
scanf("%d %d",&x,&y);
--x; --y;
if(pos[x] == pos[y]) {
printf("%d\n", y - x + );
continue;
}
int lmax = preSum[pos[x]] - x;
int rmax = y + - preSum[pos[y] - ];
int res = max(lmax, rmax);
if(pos[y] == pos[x] + ) {
printf("%d\n", res);
} else {
ql = pos[x] + + ;
qr = pos[y] - + ;
printf("%d\n", max(res, query(, , len)));
}
}
}
return ;
}
然后是 RMQ 的:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
#define For(i,s,t) for(int i = (s); i < (t); ++i)
const int N = ; int c[N];
vector<int> seq, preSum;
int pos[N] = {,}; int d[N][];
inline void init(int n)
{
For(i, , n) {
d[i][] = seq[i];
}
for(int j = ; ( << j) < n; ++j) {
for(int i = ; i + ( << j) - < n; ++i) {
d[i][j] = max(d[i][j - ], d[i + ( << (j - ))][j - ]);
}
}
} inline int rmq(int L, int R)
{
int k = , len = R - L + ;
while(( << (k + )) < len) ++k;
return max(d[L][k], d[R - ( << k) + ][k]);
} int main()
{
int n,q;
while(~scanf("%d",&n), n) {
scanf("%d", &q);
seq.clear();
scanf("%d", c);
int curValue = c[], curNum = ;
For(i, , n) {
scanf("%d", c + i);
if(c[i] == curValue) {
++curNum;
pos[i] = pos[i - ];
} else {
seq.push_back(curNum);
curValue = c[i];
curNum = ;
pos[i] = pos[i - ] + ;
}
}
seq.push_back(curNum);
preSum.clear();
preSum.push_back(seq[]);
int len = seq.size();
For(i, , len) {
preSum.push_back(preSum[i - ] + seq[i]);
}
init(len);
int x,y;
while(q--) {
scanf("%d %d",&x,&y);
--x; --y;
if(pos[x] == pos[y]) {
printf("%d\n", y - x + );
continue;
}
int lmax = preSum[pos[x]] - x;
int rmax = y + - preSum[pos[y] - ];
int res = max(lmax, rmax);
if(pos[y] == pos[x] + ) {
printf("%d\n", res);
} else {
int ql = pos[x] + ;
int qr = pos[y] - ;
printf("%d\n", max(res, rmq(ql, qr)));
}
}
}
return ;
}
UVA 11235 Frequent values 线段树/RMQ的更多相关文章
- RMQ算法 以及UVA 11235 Frequent Values(RMQ)
RMQ算法 简单来说,RMQ算法是给定一组数据,求取区间[l,r]内的最大或最小值. 例如一组任意数据 5 6 8 1 3 11 45 78 59 66 4,求取区间(1,8) 内的最大值.数据量小 ...
- UVA 11235 Frequent values(RMQ)
Frequent values TimeLimit:3000Ms , ... , an in non-decreasing order. In addition to that, you are gi ...
- POJ 3368 Frequent values 线段树与RMQ解法
题意:给出n个数的非递减序列,进行q次查询.每次查询给出两个数a,b,求出第a个数到第b个数之间数字的最大频数. 如序列:-1 -1 1 1 1 1 2 2 3 第2个数到第5个数之间出现次数最多的是 ...
- UVA - 11235 Frequent values
2007/2008 ACM International Collegiate Programming Contest University of Ulm Local Contest Problem F ...
- [POJ] 3368 / [UVA] 11235 - Frequent values [ST算法]
2007/2008 ACM International Collegiate Programming Contest University of Ulm Local Contest Problem F ...
- HDOJ-1806 ( Frequent values ) 线段树区间合并
http://acm.hdu.edu.cn/showproblem.php?pid=1806 线段树维护区间出现频率最高的出现次数.为了维护上者,需要维护线段前后缀的出现次数,当和其他线段在端点处的字 ...
- POJ3368(Frequent values)--线段树
题目在这里 3368 Accepted 7312K 1829MS C++ 6936B 题意为给你一组数据,再给定一组区间,问你这个区间内出现次数最多的元素的次数是多少. 我还记得这题是学校校赛基础的题 ...
- UVA 11235 Frequent Values ---RMQ
大白书上的例题,具体讲解见大白书,最好用用一个Log数组直接求k,这样就是纯O(1)了 #include <iostream> #include <cstdio> #inclu ...
- UVa 11235 Frequent values (RMQ && 区间出现最多次的数的次数)
题意 : 给出一个长度为 n 的不降序序列,并且给出 q 个形如(L, R)的问询,问你这个区间出现的最多次的数的次数. 分析 : 很自然的想到将区间“缩小”,例如1 1 2 3 3 3就可以变成2 ...
随机推荐
- HQL语句:三表查询(一对多,一对多)
实体类:CrmDepartment package com.learning.crm.department.domain; import java.util.HashSet; import java. ...
- 利用WeX5给手机APP增加短信验证码功能
帖子来源:http://bbs.wex5.com/thread-70908-1-1.html 遇到一个手机APP项目客户要求注册到APP上的用户手机号必须是真实的通过X5平台整合短信发送平台接口完成了 ...
- 2018 Multi-University Training Contest 2-1007(hdu 6315)-题解
一.题意 给定一个元素个数为$N(1 \le N \le 10^5)$初始序列$a$和$b$,$a$序列的初始值全为$0$,$b$序列的初始值为$1$到$N$的一个排列.有$T(1 \le T \le ...
- JAVA中方法和变量在继承中的覆盖和隐藏(一)
我们知道,在JAVA中,子类可以继承父类,如果子类声明的方法与父类有重名的情况怎么办,大伙儿都知道要是重写,但是实际上这又分为两种情况,就是方法和变量在继承时的覆盖和隐藏问题,这些概念性的东西看似无聊 ...
- Mongodb第一步资料
学习的时候收集了部分好文章,这个文章主要收集的是下载,安装的基本资料 官方http://docs.mongodb.org/manual/tutorial/install-mongodb-on-wind ...
- Python的设计哲学
Beautiful is better than ugly. 优美胜于丑陋 Explicit is better than implicit. 明了胜于晦涩 Simple is better than ...
- 记录在Python2.7 x64 bit 下 PyQt5.8的编译过程
由于工作需要使用python下面的Qt库.PyQt现在只提供针对Python3.X系列的PyQt,所有需要自己手动编译.防止忘记,特意写下随笔记录备忘. 工 作 环境:Python版本:Python ...
- Centos 7.2基础安装和配置(含分区方案建议)
景:windows桌面运维为主的我,前几天接到一个去某客户上架安装服务器的工作任务,含糊的说要上架几台服务器顺便安装Centos系统,于是我便下载了一个Centos7.2版本的镜像,顺利的用USBwr ...
- 1.ehcache实现页面整体缓存和页面局部缓存
转自:https://www.cnblogs.com/jianjianyang/p/4933016.html 好长时间没写博客了,真的是没时间啊.ps:其实就是懒!!接下来几篇要写下缓存,这里主要写下 ...
- javascript常用验证大全
1. 长度限制 <script> function test() { if(document.a.b.value.length>50) { alert("不能超过50个字符 ...