题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23846

题目大意:给定一个升序序列,有q次询问,每次询问(L,R)出现最多的值的次数。

解题思路

非常麻烦的题目。尽管一眼就能看出来是个RMQ。

关键在于如何转化为RMQ。

首先对序列进行游程编码,压缩成pos段。

编码的同时用num[i]记录当前点在段中编号,LB[i]记录在当前段的左边界,更新code[pos](当前段的容量)

编码之后O(n)扫一遍,用num[i]、code[num[i]]和LB[i]搞出在当前段的右边界RB[i]。

则Q(L,R)的时候有以下几种情况:

①如果num[L]=num[R],则说明L,R在同一段,ans=R-L+1。

②如果num[L]≠num[R],则说明L,R不在同一段,

则整个(L,R)被划分成三段:(L,RB[L]-L+1)这些元素在同一个段中,(num[L]+1,num[R]-1)前提是num[L]+1<=num[R]-1,(R-LB[R]+1,R)这些元素在同一个段中。

由于左右段都在同一段中,max元素个数即可。中间这段混合了多个完整的段,直接st即可,注意st初始化的是段的容量。

#include "cstdio"
#include "cstring"
#include "iostream"
using namespace std;
#define maxn 100000
#define maxp 20
int RMQ[maxn][maxp],n,q,w,l,r,code[maxn],num[maxn],LB[maxn],RB[maxn];
template <class T>
inline bool read(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return ; //EOF
while(c!='-'&&(c<''||c>'')) c=getchar();
sgn=(c=='-')?-:;
ret=(c=='-')?:(c-'');
while(c=getchar(),c>=''&&c<='') ret=ret*+(c-'');
ret*=sgn;
return ;
}
void ST()
{
for(int i=;i<=n;i++) RMQ[i][]=code[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
RMQ[i][j]=max(RMQ[i][j-],RMQ[i+(<<(j-))][j-]);
}
int Query(int L,int R)
{
int k=;
while((<<(k+))<=R-L+) k++;
return max(RMQ[L][k],RMQ[R-(<<k)+][k]);
}
int Q(int L,int R)
{
if(num[L]==num[R]) return R-L+;
else
{
int a=RB[L]-L+;
int b=;
if(num[L]+<=num[R]-) b=Query(num[L]+,num[R]-);
int c=R-LB[R]+;
return max(max(a,b),c);
}
}
int main()
{
while(read(n)&&read(q)&&n)
{
memset(RMQ,,sizeof(RMQ));
memset(code,,sizeof(code));
int pos=,last=<<;
for(int i=;i<=n;i++)
{
read(w);
if(w==last)
{
LB[i]=LB[i-];
code[pos]++;//当前段容量
}
else
{
LB[i]=i; //左边界
code[++pos]=;
last=w;
}
num[i]=pos; //当前点段编号
}
for(int i=;i<=n;i++) RB[i]=LB[i]+code[num[i]]-; //右边界
n=pos;
ST();
for(int i=;i<=q;i++)
{
read(l);read(r);
printf("%d\n",Q(l,r));
}
}
}
2809497 neopenx UVA 11235 Accepted 0 KB 182 ms C++ 4.8.2 1827 B 2014-10-03 18:18:58  

UVA 11235 (游程编码+ST算法)的更多相关文章

  1. RMQ算法 以及UVA 11235 Frequent Values(RMQ)

    RMQ算法 简单来说,RMQ算法是给定一组数据,求取区间[l,r]内的最大或最小值. 例如一组任意数据 5 6 8 1 3 11 45 78 59 66 4,求取区间(1,8)  内的最大值.数据量小 ...

  2. UVA 11235 Frequent values 线段树/RMQ

    vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释**************** ...

  3. ST算法

    作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 举例: 给出一数组A[0~5] = {5,4,6,10,1,12},则区间[2,5]之间的最值为1. 方法:ST算法分成两部分:离线预处 ...

  4. 求解区间最值 - RMQ - ST 算法介绍

    解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...

  5. RMQ问题之ST算法

    RMQ问题之ST算法 RMQ(Range Minimum/Maximum Query)问题,即区间最值问题.给你n个数,a1 , a2 , a3 , ... ,an,求出区间 [ l , r ]的最大 ...

  6. RMQ之ST算法模板

    #include<stdio.h> #include<string.h> #include<iostream> using namespace std; ; ],M ...

  7. CodeForces 359D (数论+二分+ST算法)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319 题目大意:给定一个序列,要求确定一个子序列,①使得该子序 ...

  8. RMQ问题(线段树+ST算法)

    转载自:http://kmplayer.iteye.com/blog/575725 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ ...

  9. [POJ3264]Balanced Lineup(RMQ, ST算法)

    题目链接:http://poj.org/problem?id=3264 典型RMQ,这道题被我鞭尸了三遍也是醉了…这回用新学的st算法. st算法本身是一个区间dp,利用的性质就是相邻两个区间的最值的 ...

随机推荐

  1. java笔试二

    16.同步和异步有何异同,在什么情况下分别使用他们?举例说明.如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必 ...

  2. sharepoint读取启用了追加功能的多行文本的历史版本记录

    当建立多行文本栏时,有个功能就是"追加对现有文本所做的更改",这个功能启用后,这个多行文本就只运行追加内容而不允许修改以前提交的内容.常常被应用在多个用户之间的协作.问题的追踪等记 ...

  3. 16.O(logn)求Fibonacci数列[Fibonacci]

    [题目] log(n)时间Fib(n),本质log(n)求a^n. [代码]  C++ Code  12345678910111213141516171819202122232425262728293 ...

  4. 【python】lxml查找属性为指定值的节点

    假设有如下xml在/home/abc.xml位置 <A> <B id=" name="apple"/> <B id=" name= ...

  5. [MAC ] Mac-OSX下安装Git

    转载自 : http://www.cnblogs.com/shanyou/archive/2011/01/30/1948088.html Mac-OSX下安装Git是一件很简单的事,我们可以下载一个安 ...

  6. HTTP状态码整理

    状态消息 1xx:信息 消息 描述 100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求. 101 Switching Protocols 服 ...

  7. eclipse静态部署tomcat

  8. eclipse 反编译插件安装

      1.下载jad.exe和jadclipse_3.3.0.jar 2.将jad.exe拷贝到%JAVA_HOME%bin目录下,将jadclipse_3.3.0.jar拷贝到eclipse的plug ...

  9. 电话连线(codevs 1003)

    题目描述 Description 一个国家有n个城市.若干个城市之间有电话线连接,现在要增加m条电话线(电话线当然是双向的了),使得任意两个城市之间都直接或间接经过其他城市有电话线连接,你的程序应该能 ...

  10. Android中mesure过程详解

    我们在编写layout的xml文件时会碰到layout_width和layout_height两个属性,对于这两个属性我们有三种选择:赋值成具体的数值,match_parent或者wrap_conte ...