地中海气候

### Description

  数据范围:\(1<=N<=10^5,1<=K<=min(2000,N),1<=a_i,p_i<=N\)

  

Solution

  首先比较显然的是每次操作的时候肯定是取走集合中最大的那个数,所以现在的问题就变成了动态维护最大值

​  然而注意到每次添加的数字只有一个,如果说这个数字加入后成为了集合中的最大值,那么在接下来的一轮中它必定会被取走,所以我们考虑加入一个数\(x\)对最大值\(mx\)的影响:

(1)\(x>mx\),那么\(x\)在新的一轮中会马上被取走,不需要对\(mx\)进行修改之类的

(2)\(x<mx\),那么\(mx\)在新的一轮中会被取走,我们需要用一个比\(mx\)更小的数\(mx'\)更新这个它

​  注意到每次需要更新\(mx\)的时候,我们找的一定是一个比它小的数,所以找\(mx'\)的整个过程肯定是单调递减的,所以我们维护一个\(cnt\)数组记录每种数字的出现次数,然后每次更新直接暴力跳到下一个非零的\(cnt\)处即可

  这样整个算法的复杂度就是\(O(NK)\)的啦

  

​  mark:转化成比较经典的问题的时候发现复杂度还是不对,那么说明有一些特殊性质,不妨考虑单调

  

Code

#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]);
	}
}
posted @ 2018-12-19 20:37  yoyoball  阅读(166)  评论(0编辑  收藏