题目大意:给出一个非降序排列的整数数组,a1,a2,…,an,你的任务是对于一系列的询问(i,j),回答ai,ai + 1,…,aj中出现次数最多的值所出现的次数。
输入格式:多组数据,每组数据第一行输入n和q,(1 <= n ,q <= 100000)。第二行包含n个非降序排列的整数a1,a2,…,an (-100000 <= ai <= 100000)。以下q行每行包括两个整数i和j (1 <= i <= j <= n),输入结束标准为n = 0。
做法分析:注意题目说到给出的序列是非降序的,这意味着中间相同的元素会排在一起,如果不是非降序排列的还真不好做。既然是一团在一起的,可以将一团数据缩在一起,用一个二元组表示(a,b),表示值为a的元素出现b次。
对于每一对i,j询问,第i个元素所在的团,和第j个所在的团是不完整的,而中间所有的团都是完整的,先求得两边两个不完整的团的大小:ans = max(R[i] - i + 1,j - L[j] +1)。中间完整的团的查询可以用RMQ。注意特判i,j都在一个团的情况,以及一共只有两个团的情况。
这里可以用下标映射,也可以用值映射,因为下标映射我写炸了,改成了值映射。
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int maxn = 1e5 + 10;
const int mx = 18;
int n,q;
int val[maxn];
int lef[maxn * 3],rig[maxn * 3],mp[3 * maxn];
int st[maxn - 1][mx - 1];
vector<pii> g;
int Hash(int x) {
return x + 100000;
}
void init() {
memset(lef,-1,sizeof(lef));
memset(rig,-1,sizeof(rig));
memset(val,-1,sizeof(val));
memset(mp,-1,sizeof(mp));
memset(st,0,sizeof(st));
g.clear();
}
int main() {
while(scanf("%d",&n) && n) {
scanf("%d",&q);
init();
int last = 0x3f3f3f3f;
for(int i = 1; i <= n; i++) {
scanf("%d",&val[i]);
if(val[i] == last)
rig[Hash(val[i])] = i;
else {
if(i != 1) {
g.push_back(pii(val[i - 1],rig[Hash(val[i - 1])] - lef[Hash(val[i - 1])] + 1));
mp[Hash(val[i - 1])] = g.size() - 1;
}
last = val[i];
lef[Hash(val[i])] = i;
rig[Hash(val[i])] = i;
}
}
rig[Hash(val[n])] = n;
g.push_back(pii(val[n],rig[Hash(val[n])] - lef[Hash(val[n])] + 1));
mp[Hash(val[n])] = g.size() - 1;
int len = g.size() - 1;
for(int i = 0; i <= len; i++)
st[i][0] = g[i].second;
for(int j = 1; (1 << j) <= len; j++)
for(int i = 0; i + (1 << j) - 1 <= len; i++)
st[i][j] = max(st[i][j - 1],st[i + (1 << (j - 1))][j - 1]);
for(int i = 1; i <= q; i++) {
int l,r;
int ans = 0;
scanf("%d%d",&l,&r);
if(val[l] == val[r])
ans = r - l + 1;
else {
int vl = Hash(val[l]),vr = Hash(val[r]);
ans = max(rig[vl] - l + 1,r - lef[vr] + 1);
int sta = mp[vl] + 1, en = mp[vr] - 1;
if(sta <= en) {
int li = en - sta + 1;
int k = (int) (log((double)li) / log(2.0));
ans = max(ans,max(st[sta][k],st[en - (1 << k) + 1][k]));
}
}
printf("%d\n",ans);
}
}
return 0;
}