洛谷P4168
题目描述
把所有的蒲公英看成一个长度为 n n n 的序列 { a 1 , a 2 . . a n } \{a_1,a_2..a_n\} {a1,a2..an},其中 a i a_i ai 为一个正整数,表示第 i i i 棵蒲公英的种类编号。
而每次询问一个区间 [ ( ( l + x − 1 ) m o d n ) + 1 , ( ( r + x − 1 ) m o d n ) + 1 ] [((l+x-1)\mod n)+1, ((r+x-1)\mod n)+1] [((l+x−1)modn)+1,((r+x−1)modn)+1],其中 x x x 表示上一次询问的答案,需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
数据规模
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 40000 1\le n \le 40000 1≤n≤40000, 1 ≤ m ≤ 50000 1\le m \le 50000 1≤m≤50000, 1 ≤ a i ≤ 1 0 9 1\le a_i \le 10^9 1≤ai≤109, 1 ≤ l 0 , r 0 ≤ n 1 \leq l_0, r_0 \leq n 1≤l0,r0≤n。
思路
- 很明显是区间分块,预处理区间 1 ~ x 1\text{\textasciitilde} x 1~x 种类 k k k 的数量,和区间 l ~ r l\text{\textasciitilde}r l~r 里出现次数最多的种类;
- 由于种类编号十分大( 1 ≤ a i ≤ 1 0 9 1\le a_i \le 10^9 1≤ai≤109),需要离散化(可以不按种类编号大小)。
- 注意: 4 × 4 × 1 0 4 × 4 4 \times 4 \times 10^{4 \times 4} 4×4×104×4 会 Memory Limit Exceeded \text{Memory Limit Exceeded} Memory Limit Exceeded。
代码
#include<bits/stdc++.h>
typedef int int32;
#define int long long
using namespace std;
const int N = 40000 + 5, M = 200 + 5;
int n, m, a[N], b[M][N], id[N], len, x, y, c[M][M], tot, cnt, d[N], last, e[N];
map<int, int>mp;
void init()
{
len = sqrt(n);
for (int i = 1; i <= n; i++)
{
if (i % len == 1)
{
cnt++;
for (int i = 1; i <= tot; i++)
b[cnt][i] = b[cnt - 1][i];
}
b[cnt][a[i]]++;
id[i] = cnt;
}
for (int i = 1; i <= cnt; i++)
{
memset(e, 0, sizeof e);
for (int j = 1; j < i; j++)
c[i][j] = 1;
for (int j = i; j <= cnt; j++)
{
int maxi = 1;
for (int k = 1; k <= tot; k++)
{
e[k] += b[j][k] - b[j - 1][k];
if (e[k] > e[maxi])
maxi = k;
else if (e[k] == e[maxi] && d[k] < d[maxi])
maxi = k;
}
c[i][j] = maxi;
}
}
return;
}
int find(int qx, int qy)
{
int l = id[qx], r = id[qy], maxi = 1;
memset(e, 0, sizeof e);
if (id[qx - 1] != l && id[qy + 1] != r)
return d[c[l][r]];
if (r - l < 2)
{
for (int i = qx; i <= qy; i++)
{
e[a[i]]++;
if (e[a[i]] > e[maxi])
maxi = a[i];
else if (e[a[i]] == e[maxi] && d[a[i]] < d[maxi])
maxi = a[i];
}
}
else
{
maxi = c[l + 1][r - 1];
for (int i = qx; id[i] == l; i++)
{
e[a[i]]++;
int tmp = e[a[i]] + b[r - 1][a[i]] - b[l][a[i]],
pre = e[maxi] + b[r - 1][maxi] - b[l][maxi];
if (tmp > pre)
maxi = a[i];
else if (tmp == pre && d[a[i]] < d[maxi])
maxi = a[i];
}
for (int i = qy; id[i] == r; i--)
{
e[a[i]]++;
int tmp = e[a[i]] + b[r - 1][a[i]] - b[l][a[i]],
pre = e[maxi] + b[r - 1][maxi] - b[l][maxi];
if (tmp > pre)
maxi = a[i];
else if (tmp == pre && d[a[i]] < d[maxi])
maxi = a[i];
}
}
return d[maxi];
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (mp[a[i]] == 0)
mp[a[i]] = ++tot, d[tot] = a[i];
a[i] = mp[a[i]];
}
init();
while (m--)
{
cin >> x >> y;
x = (x + last - 1) % n + 1;
y = (y + last - 1) % n + 1;
if (x > y)
swap(x, y);
last = find(x, y);
cout << last << '\n';
}
return 0;
}