BZOJ4241歷史研究題解 回滾莫隊

2022-03-13 05:43:54 字數 1180 閱讀 6886

這題就是求區間權值乘以權值出現次數的最大值,一看莫隊法塊可搞,但仔細想想,莫隊的加入很容易,但是刪除需要維護許多東西,非常麻煩,於是就有dalao想出了乙個新科技--回滾莫隊.回滾莫隊能使操作全部變成加入或全部變成刪除.這道題我們需要全部變成加入.

怎麼做呢?我們對詢問進行處理,左端點在乙個塊中的先歸在一起,然後以右端點為關鍵字進行排序,使得右端點靠前的在前.然後依次處理按左端點歸好後每個塊中的詢問,我們找到塊中最靠後的左端點,和最靠前的右端點(其實就是塊中第乙個詢問的右端點),統計區間資訊。

對於每乙個詢問,先移動右端點加入元素,然後左端點左移得到詢問答案後再向右移撤銷,由於不需要維護什麼資訊撤銷變得非常容易.簡單來說,總的思路就是先找出最「窄」的區間,然後不斷加入補全到詢問區間.

當然,如果詢問的左端點和右端點在乙個塊中就直接暴力處理

#include #include #include #include #include #include #include #include #include #define ll long long

#define ri register int

using std::min;

using std::max;

using std::vector;

using std::map;

template inline void read(t &x)

struct qur

bool operator <(const qur & b)const

int main()w[i]=g[w[i]];

pos[i]=(i-1)/blo+1;

}for(ri i=1;i<=q;i++)

else

}int ll,rr;ll last;

for(ri i=1;i<=pos[n];i++){//處理每個詢問塊

if(qry[i].empty())continue;

memset(cnt,0,sizeof(cnt));res=-inf;

sort(qry[i].begin(),qry[i].end());

l=mxl[i],r=qry[i][0].r;

for(ri j=l;j<=r;j++)add(w[j]);

for(ri j=0;j關於這題的離散化處理,我還進行了一些比較,在這篇部落格中

學習筆記-幾種離散化方式/

推薦學習部落格

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...