題目描述
ioi國歷史研究的第一人——joi教授,最近獲得了乙份被認為是古代ioi國的住民寫下的日記。joi教授為了通過這份日記來研究古代ioi國的生活,開始著手調查日記中記載的事件。
日記中記錄了連續n天發生的時間,大約每天發生一件。
事件有種類之分。第i天(1<=i<=n)發生的事件的種類用乙個整數xi表示,xi越大,事件的規模就越大。
joi教授決定用如下的方法分析這些日記:
現在你被要求製作乙個幫助教授分析的程式,每次給出分析的區間,你需要輸出重要度的最大值。
輸入第一行兩個空格分隔的整數n和q,表示日記一共記錄了n天,詢問有q次。
接下來一行n個空格分隔的整數x1...xn,xi表示第i天發生的事件的種類
接下來q行,第i行(1<=i<=q)有兩個空格分隔整數ai和bi,表示第i次詢問的區間為[ai,bi]。
輸出輸出q行,第i行(1<=i<=q)乙個整數,表示第i次詢問的最大重要度
樣例輸入
5 59 8 7 8 9
1 23 4
4 41 4
2 4樣例輸出98
81616題解
分塊本題卡$o(n\sqrt n\log n)$,所以不能使用莫隊(親測被卡出*),使用分塊的話也不能帶log。
考慮到一段區間內的答案,只有可能是整塊的答案,或者是塊外出現的數在這個區間內的答案。證明很簡單,略了。
對於整塊的答案,我們可以開乙個桶,然後用$o(n\sqrt n)$的時間預處理。
對於區間外的答案,除了暴力掃出塊外的數的出現次數,還要知道塊內某數出現的次數。所以還需要再預處理出前i塊中某數的出現次數,然後字首相減即可。
需要乙個離散化,但是不要忘記在求答案時反離散化回來。
時間複雜度$o(n\sqrt n)$
#include #include #include #include #define n 100010using namespace std;
typedef long long ll;
int a[n] , val[n] , cnt[n] , num[410][n];
ll ans[410][410];
int main()
for(i = 0 ; i <= (n - 1) / si ; i ++ ) }
memset(cnt , 0 , sizeof(cnt));
while(m -- )
else
printf("%lld\n" , maxn);
} return 0;
}
bzoj4241 歷史研究 分塊
popoqqq大神的題解 分塊後,處理出mx i j 表示第i塊到第j塊的答案,cnt i j 表示前i塊數字j的個數,注意先離散化。然後每次查詢,把塊外的部分單獨處理,塊內的部分直接寫答案就可以了。include include include include include include de...
bzoj 4241 歷史研究 分塊
首先分成n 0.5塊,然後答案顯然是中間一整段的最大值,或者是兩端零星的部分。那麼可以得到f i j 表示第i塊到第j塊的答案 然後就需要快速求出零星部分出現的次數,用乙個字首和s i j 表示在前i塊中j出現的次數。離散化搞一搞。好像莫隊也是可以的把。ac 如下 include include i...
bzoj4241 歷史研究 分塊
傳送門 ioi國歷史研究的第一人 joi教授,最近獲得了乙份被認為是古代ioi國的住民寫下的日記。joi教授為了通過這份日記來研究古代ioi國的生活,開始著手調查日記中記載的事件。日記中記錄了連續n天發生的時間,大約每天發生一件。事件有種類之分。第i天 1 i n 發生的事件的種類用乙個整數xi表示...