「Ynoi2019模拟赛」Yuno loves sqrt technology III

sqrt technology?

传送门

洛谷P5048

题解

题目名字告诉你应该用分块。

首先可以$O(n\sqrt{n})$地预处理出块与块之间的众数的出现次数。

然后对于每一种数字,开一个vector,存下每次出现的位置。

并记录下每个位置的数字在vector中的下标。

询问的时候,中间完整的几块直接调用预处理出的出现次数,把这个出现次数作为答案的初值。

然后考虑两边不完整的块该如何处理。

设询问的区间为$[L,R]$,先考虑左侧不完整的块,设$pos[i][j]$表示数字$i$第$j$次出现时在原序列中的位置。$vec[i]$表示第$i$个位置上的数字在$pos$数组中的第二个下标,如果满足$pos[A[i]][vec[i]+ans]<=R$,那么说明当前的答案偏小了,执行$ans++$。右侧同样处理。

总时间复杂度仍为$O(n\sqrt{n})$。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include<map>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500005;
int n,m,S,A[maxn],B[maxn],cnt[710][710],hsh[maxn],Area[maxn],vec[maxn],ans;vector<int> pos[maxn];
struct FastIO
{
static const int S=1048576;
char buf[S],*L,*R;int stk[20],Top;
~FastIO(){clear();}
inline char nc(){return L==R&&(R=(L=buf)+fread(buf,1,S,stdin),L==R)?EOF:*L++;}
inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
inline void pc(char ch){Top==S&&(clear(),0);buf[Top++]=ch;}
template<typename _Tp>
FastIO& operator >> (_Tp& ret)
{
ret=0;int f=1;char ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=nc();}
while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=nc();}
ret*=f;return *this;
}
FastIO& operator << (int x)
{
if(x<0){pc('-');x=-x;}
do{stk[++stk[0]]=x%10;x/=10;}while(x);
while(stk[0]) pc('0'+stk[stk[0]--]);
return *this;
}
FastIO& operator << (char ch){pc(ch);return *this;}
}fin,fout;
inline void Discretization()
{
map<int,int> hsh;
for(int i=1;i<=n;i++) B[i]=A[i];
sort(B+1,B+1+n);
int len=unique(B+1,B+1+n)-B-1;
for(int i=1;i<=len;i++) hsh[B[i]]=i;
for(int i=1;i<=len;i++) pos[i].push_back(0);
for(int i=1;i<=n;i++) A[i]=hsh[A[i]];
}
inline void Init()
{
for(int i=1;i<=n;i++) Area[i]=(i-1)/S+1;
for(int i=1;i<=Area[n];i++)
{
int now=0;
for(int j=i;j<=Area[n];j++)
{
for(int k=(j-1)*S+1;Area[k]==j;k++)
{
hsh[A[k]]++;
if(hsh[A[k]]>now) now=hsh[A[k]];
}
cnt[i][j]=now;
}
memset(hsh,0,sizeof(hsh));
}
for(int i=1;i<=n;i++)
{
pos[A[i]].push_back(i);
vec[i]=pos[A[i]].size()-1;
}
}
inline int Solve(int L,int R)
{
int ret=cnt[Area[L]+1][Area[R]-1];
if(Area[R]-Area[L]<=1)
{
for(int i=L;i<=R;i++)
{
hsh[A[i]]++;
if(hsh[A[i]]>ret) ret=hsh[A[i]];
}
for(int i=L;i<=R;i++) hsh[A[i]]=0;
return ret;
}
for(int i=L;Area[i]==Area[L];i++)
while(vec[i]+ret<(int)pos[A[i]].size()&&pos[A[i]][vec[i]+ret]<=R)
ret++;
for(int i=R;Area[i]==Area[R];i--)
while(vec[i]-ret>0&&pos[A[i]][vec[i]-ret]>=L)
ret++;
return ret;
}
int main()
{
fin>>n>>m;S=sqrt(n)+1e-10;
for(int i=1;i<=n;i++) fin>>A[i];
Discretization();
Init();
while(m--)
{
int L,R;fin>>L>>R;
ans=Solve(L^ans,R^ans);
fout<<ans<<'\n';
}
return 0;
}