数据范围:\(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]); } }