地中海氣候

2021-09-07 09:18:05 字數 1246 閱讀 1159

有乙個包含 n 個正整數的序列,序列元素不大於 n。緊接著,他們維護了一

個可重集合 s,包含序列中的前 p 個元素。alice 先手,二人輪流進行下面的一

系列操作:

從集合 s 中拿走乙個元素,加到玩家的總分上面;

將序列中的下乙個數字(如果存在)新增到集合 s 中;

假使二人都盡力使自己的總分最大,設遊戲的結果為 alice 的總分與 bob 的

總分之差,那麼請你在給定序列和集合元素的情況下,輸出遊戲的結果

n<=100000,q<=2000

為了簡單,我們可以看做本來只有p-1個元素,然後是先插入,再取出

比較顯然的性質是,每次都是取的multiset中最大那個元素

於是我們就直接上個multiset或者優先佇列,成功得到再nlogn的時間內搞定每次詢問

那麼現在的問題是怎麼優化呢

我們必須優化到o(n)內完成每次查詢

必須發現的一點是,每次我們只會往這個multiset中插乙個值,而且如果這個值大於了當前的最大值,就一定會被馬上取走

那麼也就是說,這個最大值一定是不增的

那麼如果當前增加值是大於這個最大值,就一定給當前的人加上這麼多分

那如果不是呢?我們會取出最大值,然後插入當前的這個值。

那麼問題來了怎麼實現呢?

二分鍊錶?或者乾脆直接上個二叉堆?似乎那個log怎麼都砍不掉啊?

然而…考慮到所有數都小於等於n,我們可以直接用乙個陣列來維護出現次數…成功實現o(1)插入,然後更新最大值暴力更新即可,由於是單調不增的,可以證明是o(n)的

於是最後o(nq)解決本題

記得開ll

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

const

int n=

100005

;int n,m;

int a[n]

,cnt[n]

;int

main()

ll ans=0;

for(

int j=

1,k=

1;j<=n;j++

,k*=-1

)}else

}printf

("%lld\n"

,ans);}

}