「51nod1689」逛街

做法:维护3个堆(有贡献堆,无贡献堆,垃圾堆)。然后将$b_i$前k小个$c_i=1$的点丢进有贡献堆,将其他的能进点丢进无贡献堆,将暂时不能进的点丢进垃圾堆。

具体实现看代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 inline ll read() {
 6     ll x=0,f=1; char ch=getchar();
 7     while(ch<'0'||ch>'9') { if(ch=='-') f=-f; ch=getchar(); } 
 8     while(ch>='0'&&ch<='9')
 9         x=x*10+ch-'0',ch=getchar();
10     return x*f;
11 }
12 #define _ read();
13 #define ln endl
14 const int N=1e5+5; 
15 int n,t,k,a[N],b[N],c[N],ans;  
16 ll sum[2]; 
17 priority_queue<int> q[2]; 
18 priority_queue< int,vector<int>,greater<int> > Q; 
19 int main() {
20     n=_; t=_; k=_; ans=-1;
21     for( int i=1;i<=n;i++ ) a[i]=_;
22     for( int i=1;i<=n;i++ ) b[i]=_;
23     for( int i=1;i<=n;i++ ) c[i]=_;
24     for( int i=1;i<=n;i++ ) {
25         q[c[i]].push(b[i]); sum[c[i]]+=b[i];
26         if(q[1].size()>k) { int now=q[1].top(); q[0].push(now); q[1].pop(); sum[1]-=now; sum[0]+=now; } 
27         if(q[1].size()<k) continue;
28         if(sum[1]+a[i]>t) continue;
29         int T=t-sum[1]-a[i];
30         while(!Q.empty()&&!q[0].empty()&&Q.top()<q[0].top()) { //把垃圾堆里面的数和目前最大的数比较 
31             int now=Q.top(),tmp=q[0].top(); sum[0]+=now; sum[0]-=tmp; 
32             Q.pop(); Q.push(tmp); q[0].pop(); q[0].push(now); 
33         }
34         while(sum[0]>T&&!q[0].empty()) { //如果目前无贡献堆里的代价太大,把代价大的丢进垃圾堆里 
35             int now=q[0].top(); q[0].pop(); 
36             sum[0]-=now; Q.push(now); 
37         }
38         while(!Q.empty()&&sum[0]+Q.top()<=T) { //如果当前无贡献堆里的代价够小,把垃圾堆里代价小的丢尽无贡献堆里 
39             int now=Q.top(); Q.pop(); 
40             sum[0]+=now; q[0].push(now);
41         }
42         if(sum[1]+sum[0]+a[i]<=t) ans=max(ans,k+(int)q[0].size());
43     } cout<<ans<<ln;
44 }
「51nod1689」逛街
原文地址:https://www.cnblogs.com/gllonkxc/p/11301360.html