POJ 3368 Frequent values (ST表)
Posted hhlya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3368 Frequent values (ST表)相关的知识,希望对你有一定的参考价值。
题面
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 frequent value among the integers ai , ... , aj.
题解
给你一个序列,然后有m次的查询,每次查询给你左右端点,问你区间内的最长连续序列是多长(元素全部相同)。区间询问,考虑st表,那么我们统计每个序列是以它为值的答案序列的第几项。然后因为是有序序列,所以查询的时候先二分出大于他的哪个元素下标,然后对前一个与右边界比较,如果大于那么就询问的区间长度就是答案吗,如果不是的话,那么我们就比较二分到的长度,和后半部分的答案,去取max,后半部分的答案可以用st表来维护(维护num值)。
代码实现
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
typedef pair<int,int> PII;
void check_min (int &a,int b) {a=min (a,b);}
void check_max (int &a,int b) {a=max (a,b);}
int n,m;
int data[maxn],num[maxn],dp[20][maxn];
inline void RMQ () {
for (int i=1;i<=n;i++) dp[0][i]=num[i];
int k=__lg (n+1);
for (int j=1;j<=k;j++)
for (int i=1;i+(1<<j-1)<=n;i++) {
dp[j][i]=max (dp[j-1][i],dp[j-1][i+(1<<(j-1))]);
}
return ;
}
int ask (int x,int y) {
int k=__lg (y-x+1);
return max (dp[k][x],dp[k][y-(1<<k)+1]);
}
int main () {
while (scanf ("%d",&n)) {
memset (num,0,sizeof (num));
// for (int i=1;i<=n;i++) printf ("%d ",num[i]);
// printf ("
");
if (n==0) break;
scanf ("%d",&m);
for (int i=1;i<=n;i++) scanf ("%d",&data[i]);
for (int i=1;i<=n;i++) {
if (i==1||data[i]!=data[i-1]) num[i]=1;
else num[i]=num[i-1]+1;
}
RMQ ();
// for (int i=1;i<=n;i++) printf ("%d ",&num[i]);
// printf ("
");
while (m--) {
int a,b,ans=1;
scanf ("%d%d",&a,&b);
int pos=upper_bound (data+1,data+1+n,data[a])-data;
if (pos>b) ans=b-a+1;
else {
ans=pos-a;
check_max (ans,ask (pos,b));
}
printf ("%d
",ans);
}
}
return 0;
}
以上是关于POJ 3368 Frequent values (ST表)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3368 Frequent values (ST表)
POJ 3368 Frequent values(线段树区间合并)