題解 BZOJ4241 歷史研究 魔改莫隊

2022-02-23 19:51:38 字數 1455 閱讀 3557

真的是好題啊

給你乙個序列和很多組詢問(可以離線),問你這個區間中\(\max\)

ioi國歷史研究的第一人——joi教授,最近獲得了乙份被認為是古代ioi國的住民寫下的日記。joi教授為了通過這份日記來研究古代ioi國的生活,開始著手調查日記中記載的事件。

日記中記錄了連續n天發生的時間,大約每天發生一件。

事件有種類之分。第i天(1<=i<=n)發生的事件的種類用乙個整數xi表示,xi越大,事件的規模就越大。

joi教授決定用如下的方法分析這些日記:

\1. 選擇日記中連續的一些天作為分析的時間段

\2. 事件種類t的重要度為t*(這段時間內重要度為t的事件數)

\3. 計算出所有事件種類的重要度,輸出其中的最大值

現在你被要求製作乙個幫助教授分析的程式,每次給出分析的區間,你需要輸出重要度的最大值。

和區間元素出現個數有關,先考慮一下莫隊。莫隊維護了元素出現個數,現在要知道元素\(\times\)權值最大值。

可以發現,你向莫隊記錄的答案中新增數是可以的,可以正確維護最大值(請意會:ans=max(ans,(ll)data[i]*cnt[i]);),但是對於要刪除元素來說不行(你莫隊套別的資料結構也不行,超時),所以我們的莫隊僅僅支援新增元素。

只能夠新增元素的莫隊?那能不能魔改一下莫隊?

考慮將詢問按照莫隊一樣的方式將詢問分塊,總共有\(o(\sqrt n)\)塊,每一塊詢問相互獨立。對於每一塊詢問,和莫隊一樣,按照右端點公升序排序。

但是可能詢問區間就小於\(\sqrt n\),為了防止我們討論邊界情況,這部分詢問直接讀入的時候就處理了。

分析一下複雜度:

總複雜度\(o(n\sqrt n)\)

這道題實際上提供了如何寫只支援新增/刪除操作的莫隊的演算法。普適性很廣。

//@winlere

#include#include#include#include#include#include#includeusing namespace std; typedef long long ll;

inline int qr()

struct e

e(const int&a,const int&b,const int&c)

inline bool operator <(const e&a)const

int main()

for(register int t=1;t<=n;++t) be[t]=(t-1)/n+1;

for(register int t=1,t1,t2;t<=m;++t)

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

return 0;

}

BZOJ4241歷史研究題解

題目連線 很顯然可以想到分塊,用f i j 表示塊i到塊j的ans,然後發現答案一定是f i j 或者其他在邊角出現的數字 我們在記下g i j 從開頭到塊i中的數字j出現的次數 這樣就每一次就統計邊角數字出現的次數,然後更新答案就好了 好像莫對也可以做。注意每一次查詢時不要memset,會t飛 i...

bzoj4241 歷史研究

這題也是坑了好久 之前whx帶我刷joi的時候本來應該要做的。可是太懶沒有寫。區間詢問加權眾數。分塊,預處理出塊和塊之間的答案,記錄到第i個塊數字x出現了多少次。然後查詢的時候和普通眾數基本一樣,就是乘了個權值而已。要離散化。時間複雜度o nlogn mn 昨晚寫的常數太爛了。用了struct,陣列...

BZOJ4241 歷史研究

一眼覺得是莫隊,發現刪除不是很好搞,於是上回滾莫隊直接搞過 回滾莫隊用於處理難以刪除但是易於新增 其實易於刪除難以新增也可以,但是沒見過這樣題 的莫隊,排序照常,如果左右端點在同一塊直接暴力,這部分最多n sqrt n,否則把左端點在一塊的一起處理,清空莫隊,然後直接令莫隊左端點在塊尾,這部分n s...