题目链接:https://ac.nowcoder.com/acm/problem/50995
题目大意:
思路:贪心+优先队列:我们按时间从小到大排序,当前时间T。并且维护已经选取的商品的最小利润。如果当前商品的时间==T。那么从优先队列来里面找到最小值如果<当前商品的利润:替换。
如果当前商品的时间<T,直接选取。
思路:并查集:我们按商品的利润从大到小排序,那么我们希望从前往后贪心。并且把每个商品放在自己过期时间前越后越好。我们用并查集来维护时间。f[i]=-1:第i天空闲。否则f[x]=y。x前面第一个空闲的天数是f[y]。
如果找到空闲天x.维护f[x]=f[x-1]
1: #include <bits/stdc++.h> #define LL long long using namespace std; struct node{ int w, t; }a[10005]; priority_queue<LL, vector<LL>, greater<LL> > q; int main(){ int n; while(~scanf("%d", &n)){ for(int i=1; i<=n; i++){ scanf("%d%d", &a[i].w, &a[i].t); } sort(a+1, a+1+n, [](node &a, node &b){return a.t<b.t;}); LL T=0, ans=0; for(int i=1; i<=n; i++){ if(T<a[i].t){ q.push(a[i].w); T++; ans+=a[i].w; } else if(a[i].w>q.top()){ ans+=(a[i].w-q.top()); q.pop(); q.push(a[i].w); } } printf("%lld\n", ans); while(!q.empty()){ q.pop(); } } return 0; } ***************************** 2: #include <bits/stdc++.h> #define LL long long using namespace std; struct node{ int w, t; }a[10005]; int f[10005]; int fd(int x){ if(f[x]==-1) return x; return f[x]=fd(f[x]); } int main(){ int n; while(~scanf("%d", &n)){ memset(f, -1, sizeof(f)); for(int i=1; i<=n; i++){ scanf("%d%d", &a[i].w, &a[i].t); } sort(a+1, a+1+n, [](node &a, node &b){return a.w>b.w;}); LL ans=0; for(int i=1; i<=n; i++){ int pos=fd(a[i].t); if(pos>0){ ans+=a[i].w; f[pos]=pos-1; } } printf("%lld\n", ans); } return 0; }