您的位置:首页 > 产品设计 > UI/UE

【RMQ问题】poj 3368 Frequent values

2015-10-05 22:17 429 查看
poj 3368 Frequent values

http://poj.org/problem?id=3368

问题描述:给你一个不减的序列,查询区间[L,R]重复次数最多的数的频度

思路: RMQ+游标编码

RMQ算法解决的是区间最小(大)值的查询问题,预处理O(nlogn),查询时间O(1),总复杂度O(nlogn+q),q为查询总次数

这道题参考大白书吧,主要是游标编码写的蛋疼,其实还是很好理解,就是分三段,第一段和第三段直接计数,中间一段对cnt[]数组RMQ即可,取三者的最大值,cnt[i]表示第i段的相同元素数目

参考代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<sstream>
#define eps 1e-9
#define pi acos(-1)
#define long long ll
#define M 10
#define N 1010
using namespace std;
const int _max = 1e5 + 10;

int l,r,n,q,a[_max],d[_max][20];
int Left[_max],Right[_max],cnt[_max],num[_max];

void RMQ_init(){
for(int i = 0; i < n; ++i) d[i][0] = cnt[i];
for(int j = 1;(1<<j) <= n; ++ j)
for(int i = 0; i + (1<<j) -1 < n; ++ i)
d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}

int RMQ(int L,int R){
if(L > R) return 0;
int k = 0;
while((1<<(k+1)) <= R-L+1) ++k;//若2^(k+1)<=R-L+1,k自加
return max(d[L][k],d[R-(1<<k)+1][k]);
}

void init(){
Left[0] = 0;
for(int i = 1; i < n; ++ i)
if(a[i]==a[i-1]) Left[i] = Left[i-1];
else Left[i] = i;
// for(int i = 0; i < n; ++ i) printf("%d ",Left[i]);cout<<endl;
Right[n-1] = n-1;
for(int i = n-1;i >= 0; -- i)
if(a[i]==a[i+1]) Right[i] = Right[i+1];
else Right[i] = i;
num[0] = 0;cnt[0] = 1;int top = 0;
for(int i = 1; i < n; ++i){
if(a[i]==a[i-1]) num[i] = num[i-1],cnt[top]++;
else num[i] = num[i-1] + 1,cnt[++top] = 1;
}
top++;
n = top;//cnt一共有n个数,从0~n-1
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif // ONLINE_JUDGE
while(scanf("%d",&n)==1&& n){
scanf("%d",&q);
for(int i = 0; i < n; ++ i) scanf("%d",a+i);
memset(cnt,0,sizeof(cnt));
init();//游标编码
RMQ_init();
int ans;
while(q--){
scanf("%d%d",&l,&r);
l--;r--;
if(num[l]==num[r]) {printf("%d\n",r-l+1);continue;}
ans = max(Right[l]-l+1,r-Left[r]+1);//区间三块最大值
ans = max(ans,RMQ(num[l]+1,num[r]-1));
printf("%d\n",ans);
}
}
return 0;
}


加粗
Ctrl + B


斜体
Ctrl + I


引用
Ctrl + Q


插入链接
Ctrl + L


插入代码
Ctrl + K


插入图片
Ctrl + G


提升标题
Ctrl + H


有序列表
Ctrl + O


无序列表
Ctrl + U


横线
Ctrl + R


撤销
Ctrl + Z


重做
Ctrl + Y
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RMQ 游标编码