「51nod1689」逛街
做法:维护3个堆(有贡献堆,无贡献堆,垃圾堆)。然后将$b_i$前k小个$c_i=1$的点丢进有贡献堆,将其他的能进点丢进无贡献堆,将暂时不能进的点丢进垃圾堆。
具体实现看代码
1 #include「51nod1689」逛街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() 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() 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<ln; 44 }