題目
回滾莫隊,大概是一種莫隊的小trick
對序列分塊,對於左右端點在同乙個塊裡的直接暴力;其餘的詢問按照左端點所在塊分類,乙個塊內按照右端點公升序排序
我們維護乙個指標\(rp\)記錄當前右端點的位置,對於乙個詢問\([l,r]\),設其所在塊的右端點為\(r\),我們將\(rp\)暴力移動到\(r\)的位置;由於右端點單調,移動過程只有加入,當移動到\(r\)的時候,我們再將\([l,r]\)內的數暴力加入,進行詢問;詢問完後要將\([l,r]\)內的數產生的影響撤銷掉;做完乙個塊內的詢問我們暴力清除所有貢獻就好了
分析一下複雜度,設塊大小為\(b\),那麼右指標移動的暴力清桶的複雜度是\(o(\fracn)\),加入零散塊和撤銷的複雜度是\(o(bm)\),所以在\(b=\frac}\)的時候複雜度是\(o(n\sqrt)\)
對於這道題,我們如果使用普通莫隊的話需要加乙個堆來維護刪除時的最大值,複雜度是\(o(n\sqrt\log n)\)的,回滾莫隊只需要在暴力加入零散塊時記錄一下原來的最大值就好了
**
#include#define re register
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
const int maxn=1e5+5;
inline int read()
struct askq[maxn];
int b,n,m,sz,a[maxn],tax[maxn],b[maxn],id[maxn],num,lb[maxn],rb[maxn],tot;
ll ans[maxn],ans,nw;
inline int cmp(const ask &a,const ask &b)
for(re int i=1;i<=m;i++)
} std::sort(q+1,q+tot+1,cmp);q[tot+1].l=0;
for(re int k=1,i=1;i<=tot;i++)
for(re int i=1;i<=m;i++)printf("%lld\n",ans[i]);return 0;
}
AT1219 歷史研究
ioi 國歷史研究的第一人 joi 教授,最近獲得了乙份被認為是古代 ioi 國的住民寫下的日記。joi 教授為了通過這份日記來研究古代 ioi 國的生活,開始著手調查日記中記載的事件。日記中記錄了連續 n 天發生的時間,大約每天發生一件。事件有種類之分。第 i 天 1 i n 發生的事件的種類用乙...
4241 歷史研究
這一題我還是不會做qaq 一開始想了一想,好像可以上莫隊 嗯,怎麼維護修改呢 我們可以對數值進行分塊啊,那麼每次就只需要n 的時間就可以維護好了 v 嗯,看起來是乙個十分優越的做法 時間複雜度就是莫隊 n 也就是n nn 大概是n2 這就跟暴力沒什麼區別嘛,就名字好聽了一點 於是繼續想。什麼都沒想出...
bzoj4241 歷史研究
這題也是坑了好久 之前whx帶我刷joi的時候本來應該要做的。可是太懶沒有寫。區間詢問加權眾數。分塊,預處理出塊和塊之間的答案,記錄到第i個塊數字x出現了多少次。然後查詢的時候和普通眾數基本一樣,就是乘了個權值而已。要離散化。時間複雜度o nlogn mn 昨晚寫的常數太爛了。用了struct,陣列...