[題解](貪心/堆)luogu_P2107小Z的AK計劃

清明講過一道類似的,難度略大的:P3545 [POI2012]HUR-Warehouse Store

兩道題類似,都是暫時先把前面的加進候選集合里,如果超出限制的話就拿現在這個和前面的交換,

相當於不選前面那個選當前這個,應該是比較好的思想

這道題還有一個就是如果最優解要你走到那個點,那麼中間的路程是不可省略的,所以貪心時大可不考慮

反正實質上是個dp,取的是最大值

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100010;
ll n,m,cnt,sum,ans,tmp;
struct node{
    ll x,t;
}a[maxn];
bool cmp(node a,node b){return a.x<b.x;}
int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        ll x,t;scanf("%lld%lld",&x,&t);
        if(x<=m && t<=m)
        a[++cnt].x=x,a[cnt].t=t;
    }
    sort(a+1,a+1+cnt,cmp);
    priority_queue<ll>q;
    for(int i=1;i<=cnt;i++){
        sum+=a[i].t+a[i].x-a[i-1].x;//先選上這次的 
        q.push(a[i].t);
        tmp++;
        while(sum>m){//要超過時限就替換最大的 
            sum-=q.top();q.pop();
            tmp--;
        }
        ans=max(ans,tmp);//根本上是个dp,取f[1]~f[n]最大值 
    }
    printf("%lld",ans);
}

另一題的代碼

//by jackpei
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int maxn=250010;
struct node{
    int val,t;
    node(int vv,int tt){
        val=vv,t=tt;
    }
    bool operator <(const node &b)const{
        return val<b.val;
    }
};

priority_queue<node>pq;
int n,a[maxn],b[maxn],vis[maxn];
ll res;
int ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++){
        res+=(a[i]-b[i]),vis[i]=1,++ans;
        pq.push(node(b[i],i));
        while(res<0)
        res+=pq.top().val,vis[pq.top().t]=0,pq.pop(),ans--;
    }
    printf("%d
",ans);
    for(int i=1;i<=n;i++)
    if(vis[i])printf("%d ",i);
}