图灵杯 E 简单的RMQ(UVA 11235)(RMQ)

E: 简单的RMQ

时间限制: 2 Sec  内存限制: 64 MB
提交: 934  解决: 165
[提交][状态][讨论版]

题目描述

给定一个数组,其中的元素满足非递减顺序。任意给定一个区间[i,j],求其中某个元素重复出现的最大次数。

输入

多组数据输入。每组数据的第一行包含两个整数n和q(1<=n,q<=100000),下一行包含n个整数a1,...,an(-100000<=ai<=100000,i∈{1,...,n}),用空格分隔,数列是升序的(ai<=ai+1)。接下来的q行,每行包含两个整数i和j(1<=i<=j<=n),表示给定区间[i,j]。
输入结束于0(自成一行)。

输出

对输入的q个区间,每个区间输出一个整数表示该区间内重复最多的元素出现的次数,用换行分隔。

样例输入

10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0

样例输出

1
4
3【分析】直接区间RMQ,需要注意的是更新和查找时判一下两区间交点处的情况。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 2e5+50;
const int mod = 1e9+7;
const double pi= acos(-1.0);
typedef pair<ll,int>pii;
int mx[N][18];
int mm[N],n,q;
int l[N],r[N],a[N];
void init() {
    for(int j=1; j<=mm[n]; ++j) {
        for(int i=1; i+(1<<j)-1<=n; ++i) {
            int mid=i+(1<<(j-1));
            int ll=max(i,l[a[mid]]);
            int rr=min(i+(1<<j)-1,r[a[mid]]);
            mx[i][j]=max(rr-ll+1,max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]));
        }
    }
}
int getmx(int ll,int rr) {
    int k = mm[rr-ll+1];
    int l1=max(ll,l[a[ll+(1<<k)]]);
    int r1=min(rr,r[a[ll+(1<<k)]]);
    int l2=max(ll,l[a[rr-(1<<k)+1]]);
    int r2=min(rr,r[a[rr-(1<<k)+1]]);
    int ret=1;
    ret=max(r1-l1+1,r2-l2+1);
    ret=max(ret,max(mx[ll][k],mx[rr-(1<<k)+1][k]));
    return ret;
}
int main() {
    mm[0]=-1;
    for(int i=1; i<N; ++i)mm[i]=(i&(i-1))?mm[i-1]:mm[i-1]+1;
    while(~scanf("%d",&n)&&n) {
        met(l,0);
        scanf("%d",&q);
        for(int i=1; i<=n; ++i) {
            scanf("%d",&a[i]);
            a[i]+=100000;
            if(!l[a[i]])l[a[i]]=i;
            r[a[i]]=i;
            mx[i][0]=1;
        }
        init();
        while(q--) {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",getmx(x,y));
        }
    }
    return 0;
}
时间: 2024-08-05 07:32:00

图灵杯 E 简单的RMQ(UVA 11235)(RMQ)的相关文章

uva 11235(RMQ)

题意:给出非降序的n个数字的序列(有重复),然后给出i,j问[i,j]范围内出现最多次数的值的次数. 题解:经典的RMQ问题,按书上题解的思路,先把序列分段,即相同数字是一个段,用val[cnt]和count[cnt]表示第cnt段的值和出现次数,num[i],l[i],r[i]分别表示位置i所在段编号(cnt),左右端点位置,那么每次查询[i,j]时,就是要计算i到i左端点的元素个数,j到j右端点的元素个数,还有num[i] + 1到num[j] - 1段的count的最大值,这三者中的最大值

UVa 11235 (RMQ) Frequent values

范围最值问题,O(nlogn)的预处理,O(1)的查询. 这个题就是先对这些数列进行游程编码,重复的元素只记录下重复的次数. 对于所查询的[L, R]如果它完全覆盖了某些连续的重复片段,那么查询的就是这几种元素重复最多的次数,也就是RMQ. 如果[L, R]还覆盖了某一部分边界,也要单独计算取最大值. 还有个特殊情况就是查询区间都在某一个元素的重复片段中,答案直接就是R-L+1 1 #include <cstdio> 2 #include <vector> 3 #include &

UVA 11235 RMQ算法

上次的湘潭赛的C题,用线段树敲了下还是WA,不知道为何,我已经注意了处理相同数据,然后他们当时用的RMQ. 所以学了下RMQ,感觉算法思想是一样的,RMQ用了DP或者是递推,由单个数到2^k往上推,虽然有部分重叠的,也没关系,因为RMQ是求区间最值嘛 然后这道题目,要把出现次数化为最值,构造一个新的数组来存贮出现次数,每次是在这个数组里面查询.细节处理要注意,比如所求的区间可能就在一个段里面,需要单独判断. #include <iostream> #include <cstdio>

uva 11235 - Frequent values(RMQ)

题目链接:uva 11235 - Frequent values 题目大意:给定一个非降序的整数数组,要求计算对于一些询问(i,j),回答ai,ai+1,-,aj中出现最多的数出现的次数. 解题思路:因为序列为非降序的,所以相同的数字肯定是靠在一起的,所以用o(n)的方法处理处每段相同数字的区间.然后对于每次询问: num[i]=num[j]:j?i+1 numi≠numj:max(RMQ(righti+1,reftj?1),max(righti?i+1,j?leftj+1)) #include

UVA 11235 Frequent values 线段树/RMQ

vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释************************************************************ 题目大意:给出一个非降序排列的整数数组 a1,a2,a3,...,an,你的任务是对于一系列询问 (i, j),回答 ai,ai+1,...,aj 中出现次数最多的值所出现的次数. 输入格式:包含多组数据.每组

UVA 11235 Frequent values(RMQ)

Frequent values TimeLimit:3000Ms You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most f

UVA 11235 (游程编码+ST算法)

题目链接: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)扫一遍,用nu

UVA 11235 Frequent values

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int maxn=100005; 7 8 int count[maxn]; 9 int num[maxn],ll[maxn],rr[maxn]; 10 int tot; 11 int d[maxn][50]; 12 13 int rmq (int l,int r){ 14 int

Uva 12299 RMQ with Shifts(线段树 + 单点更新 )

Uva 12299 RMQ with Shifts (线段树 + 单点更新) 题意: 对于给定的序列 x[i]给出一个操作 shift(a,b,c,d,e) 对应的是将 x[a]与x[b] x[b]与x[c] 这样相邻的两两交换For example, if A={6, 2, 4, 8, 5, 1, 4}then shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields {8, 6, 4, 5, 4