數據範圍:\(1<=N<=10^5,1<=K<=min(2000,N),1<=a_i,p_i<=N\)ios
首先比較顯然的是每次操做的時候確定是取走集合中最大的那個數,因此如今的問題就變成了動態維護最大值c++
然而注意到每次添加的數字只有一個,若是說這個數字加入後成爲了集合中的最大值,那麼在接下來的一輪中它一定會被取走,因此咱們考慮加入一個數\(x\)對最大值\(mx\)的影響:算法
(1)\(x>mx\),那麼\(x\)在新的一輪中會立刻被取走,不須要對\(mx\)進行修改之類的數組
(2)\(x<mx\),那麼\(mx\)在新的一輪中會被取走,咱們須要用一個比\(mx\)更小的數\(mx'\)更新這個它spa
注意到每次須要更新\(mx\)的時候,咱們找的必定是一個比它小的數,因此找\(mx'\)的整個過程確定是單調遞減的,因此咱們維護一個\(cnt\)數組記錄每種數字的出現次數,而後每次更新直接暴力跳到下一個非零的\(cnt\)處便可code
這樣整個算法的複雜度就是\(O(NK)\)的啦blog
mark:轉化成比較經典的問題的時候發現複雜度仍是不對,那麼說明有一些特殊性質,不妨考慮單調ip
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=1e5+10; int a[N],cnt[N]; ll sum[2]; int n,m; int main(){ #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); #endif int x,mx,who,recmx; scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",a+i); for (int o=1;o<=m;++o){ scanf("%d",&x); mx=0; for (int i=1;i<=x;++i){ ++cnt[a[i]]; mx=max(mx,a[i]); } who=0; sum[0]=sum[1]=0; recmx=0; for (int i=x+1;mx||recmx;++i,who^=1){ if (recmx){ sum[who]+=recmx; recmx=0; } else{ sum[who]+=mx; --cnt[mx]; while (cnt[mx]==0&&mx) --mx; } if (i>n) continue; if (a[i]>mx) recmx=a[i]; else ++cnt[a[i]]; } printf("%lld\n",sum[0]-sum[1]); } }