BZOJ4241 歷史研究 回滾莫隊

2022-05-25 14:24:08 字數 1165 閱讀 2667

題目描述:給出乙個長度為\(n\)的陣列,每次詢問區間 \([l,r]\),求 \(\max\limits_x*cnt_x\),其中 \(cnt_x\) 表示 \(x\) 在區間 \([l,r]\) 的出現次數。

資料範圍:\(n\le 10^5,a_i\le 10^9\)。

分塊也可以做到 \(o(n\sqrt)\),但是空間也是 \(o(n\sqrt)\)。使用回滾莫隊可以在 \(o(n)\) 空間內解決。

首先上來離散化,然後考慮莫隊。發現這個東西增加乙個數是 \(o(1)\) 的,但刪除乙個數至少要 \(o(\log n)\) 才能做,所以我們考慮只增。首先詢問按照普通莫隊的方法排序,然後處理 \(l\) 在一塊,而且 \(r\) 遞增的詢問。設塊的右端點為 \(mid\),則 \((mid,r]\) 可以只新增數來解決,而 \([l,mid]\) 這一段直接暴力(長度 \(\sqrt\))。總時間複雜度是 \(o(n\sqrt)\) 的。

於是像區間眾數這種東西也可以用回滾莫隊做了。

code

```cpp

#include#define rint register int

using namespace std;

typedef long long ll;

const int n = 100003;

int n, m, blo, x[n], val[n], len, ql, qr, mid;

ll cnt[n], qans, ans[n], tt[n];

struct query

} q[n];

inline void add(int x)

inline void del(int x)

int main()

if(q[i].l / blo == q[i].r / blo)

while(qr <= q[i].r) add(x[qr]), ++ qr;

ll tmp = qans;

while(ql > q[i].l) -- ql, add(x[ql]);

ans[q[i].id] = qans;

while(ql < mid) del(x[ql]), ++ ql;

qans = tmp;

} for(rint i = 1;i <= m;i ++) printf("%lld\n", ans[i]);

}```

bzoj4241 歷史研究 回滾莫隊

ioi國歷史研究的第一人 joi教授,最近獲得了乙份被認為是古代ioi國的住民寫下的日記。joi教授為了通過這份日記來研究古代ioi國的生活,開始著手調查日記中記載的事件。日記中記錄了連續n天發生的時間,大約每天發生一件。事件有種類之分。第i天 1 i n 發生的事件的種類用乙個整數xi表示,xi越...

bzoj4241 歷史研究 回滾莫隊

題目大意 給定乙個長度為n nn的序列,有q qq個詢問,要求回答區間 l,r l,r l,r 內,出現過的權值與其出現次數的積的最大值。n m 1 05 n,m 10 5 n,m 1 05首先這道題一看就是莫隊qwq 然後發現如果只有插入操作是很容易的,珂以直接o n n o n sqrt o n...

練習 BZOJ4241 歷史研究(回滾莫隊)

給定乙個長度為 n n 的序列,並提出 q role presentation q q個詢問,每次詢問要求回答區間 l r l,r 內所有的權值與其出現次數的積的最大值。我一看,區間問題,無修改可以離線,上莫隊妥妥的,但是仔細一想,當區間擴充時,可以o 1 o 1 的求出新區間答案,但是當區間縮小時...