bzoj4241 歷史研究 回滾莫隊

2021-08-22 13:45:02 字數 1741 閱讀 4720

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

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

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

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

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

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

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

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

1<=n<=10^5

1<=q<=10^5

1<=xi<=10^9 (1<=i<=n)

回滾莫隊,get到新姿勢了

對於一些能簡單插入但是不能簡單刪除的資訊可以考慮回滾莫隊

一開始寫的是莫隊+線段樹,計算一波複雜度發現並不能過就gg了

對於詢問區間(l,r),我們把起點tl設為l所在塊的右端點,tr設為l-1

不斷右移右指標tr,記下此時答案為tmp1

不斷左移左指標tl,此時答案為詢問答案

將左指標tl回滾到起點(l所在塊的右端點),將當前答案恢復為tmp1

如果當前詢問的l與上一次詢問的l所在塊相同就保留左右指標,否則重新調整起點

注意到我們對詢問的排序方式非常特殊,這種做法能夠避開刪除操作並且保持優秀的複雜度

#include 

#include

#include

#include

#define rep(i,st,ed) for (register int i=st;i<=ed;++i)

#define fill(x,t) memset(x,t,sizeof(x))

typedef

long

long ll;

const

int n=100005;

struct q q[n];

int a[n],b[n],bel[n],b;

ll ans[n],vec[n],rec[n];

int read()

bool cmp(q a,q b)

std:: sort(b+1,b+n+1);

int size=std:: unique(b+1,b+n+1)-b-1;

rep(i,1,n) a[i]=std:: lower_bound(b+1,b+size+1,a[i])-b;

rep(i,1,m) q[i]=(q) ;

std:: sort(q+1,q+m+1,cmp);

int l=1,r=0;

ll tmp1=0,tmp2=0,pos;

rep(i,1,m)

if (bel[q[i].l]==bel[q[i].r])

rep(j,q[i].l,q[i].r) vec[a[j]]-=b[a[j]];

continue;

}for (;rstd:: max(tmp1,rec[a[r]]);

}tmp2=tmp1;

for (;l>q[i].l;)

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

for (;l1,m) printf("%lld\n", ans[i]);

return

0;}

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 的陣列,每次詢問區間 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...

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

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