BZOJ傳送門
題目描述
IOI國曆史研究的第一人——JOI教授,最近獲得了一份被認爲是古代IOI國的住民寫下的日記。JOI教授爲了通過這份日記來研究古代IOI國的生活,開始着手調查日記中記載的事件。
日記中記錄了連續天發生的時間,大約每天發生一件。
事件有種類之分。第天發生的事件的種類用一個整數表示,越大,事件的規模就越大。
JOI教授決定用如下的方法分析這些日記:
-
選擇日記中連續的一些天作爲分析的時間段
-
事件種類的重要度爲*(這段時間內重要度爲的事件數)
-
計算出所有事件種類的重要度,輸出其中的最大值
現在你被要求製作一個幫助教授分析的程序,每次給出分析的區間,你需要輸出重要度的最大值。
輸入輸出格式
輸入格式
第一行兩個空格分隔的整數和,表示日記一共記錄了天,詢問有次。
接下來一行個空格分隔的整數,表示第天發生的事件的種類
接下來行,第行有兩個空格分隔整數和,表示第次詢問的區間爲。
輸出格式
輸出行,第行一個整數,表示第次詢問的最大重要度
輸入輸出樣例
輸入樣例#1:
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
輸出樣例#1:
9
8
8
16
16
解題分析
如果用普通莫隊在刪除時無法維護次大值, 需要一個, 就GG了。
所以去學了新姿勢: 回滾莫隊。
還是分塊, 把左端點在一塊的詢問按右端點從小到大排序。
如果左右端點都在一塊先處理掉。
然後我們只維護左端點在當前左端點所在塊最右端, 且右端點單調遞增的答案, 每次動態插入左邊塊內的元素統計答案後再撤銷。
總複雜度還是的。
代碼如下:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <vector>
#include <tr1/unordered_map>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 100500
#define ll long long
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
std::tr1::unordered_map <int, int> mp;
int n, m, sqr, qcnt, arr, bcnt;
ll ans[MX];
int blk[MX], val[MX], cnt[MX], id[MX];
struct Query {int l, r, id;};
IN bool operator < (const Query &x, const Query &y) {return x.r < y.r;}
std::vector <Query> que[500];
int main(void)
{
int foo, bar, cur, siz;
R ll rem, mx;
in(n), in(m); sqr = std::sqrt(n); bcnt = n / sqr;
for (R int i = 1; i <= n; ++i)
{
in(foo), blk[i] = i / sqr;
if (!mp[foo]) mp[foo] = ++arr, val[arr] = foo;
id[i] = mp[foo];
}
for (R int i = 1; i <= m; ++i)
{
in(foo), in(bar);
if (blk[foo] == blk[bar])
{
mx = 0;
for (R int j = foo; j <= bar; ++j)
{
++cnt[id[j]];
mx = max(1ll * cnt[id[j]] * val[id[j]], mx);
}
ans[i] = mx; mx = 0;
for (R int j = foo; j <= bar; ++j) --cnt[id[j]];
}
else que[foo / sqr].push_back({foo, bar, i});
}
std::sort(que + 1, que + 1 + qcnt);
for (R int i = 0; i <= bcnt; ++i)
{
std::sort(que[i].begin(), que[i].end());
std::memset(cnt, mx = 0, sizeof(cnt));
cur = (i + 1) * sqr - 1, siz = que[i].size();
for (R int j = 0; j < siz; ++j)
{
W (cur < que[i][j].r)
{
++cur;
++cnt[id[cur]];
mx = max(mx, 1ll * cnt[id[cur]] * val[id[cur]]);
}
rem = mx;
for (R int k = (i + 1) * sqr - 1; k >= que[i][j].l; --k)
{
++cnt[id[k]];
mx = max(mx, 1ll * cnt[id[k]] * val[id[k]]);
}
ans[que[i][j].id] = mx;
for (R int k = (i + 1) * sqr - 1; k >= que[i][j].l; --k) --cnt[id[k]];
mx = rem;
}
}
for (R int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
}