题意 查询区间最小众数
死啃了clj的区间众数解题报告... 真实太强辣 还有一个logn的优化 没学会 待填坑
大概就是分块 然后枚举最多2根号n + 1个元素 询问这些元素在这个区间出现了多少次
先预处理同一个元素在数组中出现的位置 存入容器中 然后二分查询即可
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
map<int, int> mp;
vector<int> val[100005];
int q[100005];
int bl[100005];
int id[100005];
int cn[100005];
int f[505][505];
int n, blo, cnt;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void pre(int x)
{
memset(cn, 0, sizeof(cn));
int ans = 0, zd = 0;
for(int i = (x - 1) * blo + 1; i <= n; i++)
{
int t = bl[i];
cn[q[i]]++;
if(cn[q[i]] > zd || (cn[q[i]] == zd && id[q[i]] < id[ans]))
ans = q[i], zd = cn[q[i]];
f[x][t] = ans;
}
}
int qu(int l, int r, int c)
{
return upper_bound(val[c].begin(), val[c].end(), r) - lower_bound(val[c].begin(), val[c].end(), l);
}
int query(int l, int r)
{
int ans, zd = 0;
for(int i = l; i <= min(r, bl[l] * blo); i++)
{
int c = qu(l, r, q[i]);
if(c > zd || (c == zd && id[q[i]] < id[ans]))
ans = q[i], zd = c;
}
if(bl[l] + 1 < bl[r])
{
int c = qu(l, r, f[bl[l] + 1][bl[r] - 1]);
if(c > zd || (c == zd && id[f[bl[l] + 1][bl[r] - 1]] < id[ans]))
ans = f[bl[l] + 1][bl[r] - 1], zd = c;
}
if(bl[l] != bl[r])
for(int i = (bl[r] - 1) * blo + 1; i <= min(r, bl[r] * blo); i++)
{
int c = qu(l, r, q[i]);
if(c > zd || (c == zd && id[q[i]] < id[ans]))
ans = q[i], zd = c;
}
return id[ans];
}
int main()
{
n = read();
blo = 200;
cnt = 0;
for(int i = 1; i <= n; i++)
{
q[i] = read();
bl[i] = (i - 1) / blo + 1;
if(!mp[q[i]])
{
cnt++;
id[cnt] = q[i];
mp[q[i]] = cnt;
}
q[i] = mp[q[i]];
val[q[i]].push_back(i);
}
for(int i = 1; i <= bl[n]; i++) pre(i);
for(int i = 1; i <= n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", query(l, r));
}
return 0;
}