前言
这道题我两年前直接爆切,两年后碰到类似的题:数据结构。
降智严重啊。
题目
题目大意:
有 (n) 瓶药剂,从左往右编号依次是 (1...n),每瓶药剂有一个值 (a_i) ,表示喝下去之后你可以增加 (a_i) 点生命值((a_i) 为负则是减少生命值)。你的初始生命值为 (0),从左往右依次选择药剂喝掉(当然也可以不喝),询问最多可以喝多少药剂。过程中要保证生命值不低于0。
(1le nle 200000;-10^9le a_ile 10^9.)
讲解
这里有一个优秀的反悔贪心做法。
只要喝不死,就往死里喝。如果喝死了,就把最毒的吐出来!
显然这是正确的,而且只需要一个优先队列即可简单实现。
还有一个蠢一点的做法:先把所有不扣血的药剂全部喝光,得到每个位置的最大生命值。然后贪心选毒性最小的药剂喝掉,用线段树维护是否会毒死。
不过这样实现十分冗长。
代码
std
#include <bits/stdc++.h>
using namespace std;
int main(){
ios_base::sync_with_stdio(false); cin.tie(0);
int n; cin >> n;
priority_queue<long long, vector<long long>, greater<long long> > pq;
long long S = 0;
for(int i = 1;i <= n;i++){
long long x; cin >> x;
S += x;
pq.push(x);
while(S < 0){
S -= pq.top();
pq.pop();
}
}
cout << (int) pq.size();
}
我就是这个做法...
int h;
struct node
{
int val,ID;
bool operator < (const node &px)const{
if(val != px.val) return val > px.val;
return ID > px.ID;
}
}s[MAXN];
#define lc (x<<1)
#define rc (x<<1|1)
struct SegmentTree
{
LL MIN[MAXN << 2],lz[MAXN << 2];
void up(int x){MIN[x] = Min(MIN[lc],MIN[rc]);}
void down(int x){
if(!lz[x]) return;
lz[lc] += lz[x];
lz[rc] += lz[x];
MIN[lc] += lz[x];
MIN[rc] += lz[x];
lz[x] = 0;
return;
}
void Build(int x,int l,int r)
{
if(l == r) {MIN[x] = a[l];lz[x] = 0;return;}
int mid = (l+r) >> 1;
Build(lc,l,mid); Build(rc,mid+1,r);
up(x);
}
void Add(int x,int l,int r,int ql,int qr,LL val)
{
if(ql <= l && r <= qr) {MIN[x] += val;lz[x] += val;return ;}
down(x);
int mid = (l+r) >> 1;
if(ql <= mid) Add(lc,l,mid,ql,qr,val);
if(mid+1 <= qr) Add(rc,mid+1,r,ql,qr,val);
up(x);
}
LL Query(int x,int l,int r,int ql,int qr)
{
if(ql <= l && r <= qr) return MIN[x];
down(x);
LL mid = (l+r) >> 1,ret = INF;
if(ql <= mid) ret = Min(ret,Query(lc,l,mid,ql,qr));
if(mid+1 <= qr) ret = Min(ret,Query(rc,mid+1,r,ql,qr));
return ret;
}
}st;
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read();
for(int i = 1;i <= n;++ i)
{
a[i] = Read();
if(a[i] >= 0) ans++,S += a[i],a[i] = S;
else s[++h].val = a[i],s[h].ID = i,a[i] = S;
}
st.Build(1,1,n);
sort(s+1,s+h+1);
for(int i = 1;i <= h;++ i)
{
LL M = st.Query(1,1,n,s[i].ID,n);
if(M < Abs(s[i].val)) continue;
ans++;
st.Add(1,1,n,s[i].ID,n,s[i].val);
}
Put(ans);
return 0;
}