题解 CF727F 【Polycarp's problems】
提供一篇贪心的题解。
题意转化:
每次给定
Solution:
首先我们考虑前缀和的本质,就是一个个正数努力去抵消负数的过程,并且一个整数只能抵消下标在自己之后的负数。
我们再次思考,每个正数会去抵消哪些负数,它一定会先消绝对值较小的,因为最后我们不管手动删去负的多的还是负的少的,代价都是
那么我们只要从后往前扫一遍,用堆来使得每个正数按最优策略消去尽量多的负数,剩下的就是要留给
然后我们对没消完的负数做个前缀和,每次二分查找
这样复杂度就是
当时写的时候没看见
Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define gc getchar()
inline ll read(){
register ll x(0),f(1);register char c(gc);
while(c>'9'||c<'0')f=c=='-'?-1:1,c=gc;
while(c>='0'&&c<='9')x=x*10+c-48,c=gc;
return f*x;
}
priority_queue<ll>q;
const int N=210000;
ll a[N],n,m,pre[N],cnt;
int main(){
n=read();m=read();
register int i;
for(i=1;i<=n;i++)a[i]=read();
for(i=n;i>=1;i--){
if(a[i]<0){
q.push(a[i]);
}
else{
while(!q.empty()&&a[i]>=0){
a[i]+=q.top();q.pop();
}
if(a[i]<0)q.push(a[i]);
}
}
while(!q.empty()){
pre[++cnt]=q.top();q.pop();
}
for(i=1;i<=cnt;i++)pre[i]=-pre[i]+pre[i-1];
while(m--){
ll x=read();
cout<<(cnt-(upper_bound(pre+1,pre+1+cnt,x)-pre)+1)<<'\n';
}
}