【权值并查集】 supermarket

传送门

题意

\(N\)个商品,每个商品有利润\(p_{i}\)和过期时间\(d_{i}\),每天只能卖出一个商品,即每个商品卖出会消耗一天时间,求最大利益

数据范围

\(\begin{array}{l}0 \leq N \leq 10000 \\ 1 \leq p_{i}, d_{i} \leq 10000\end{array}\)

题解

并查集维护时间值域
需要需注意的是过期时间靠后的利润高可以占用前面利润较低的时间,来取得利益的最大值

  • 按照利润从大到小排序
  • 初始化所有时间值域的集合都是自己
  • 遍历利润从大到小的商品,每次都查询当前时间所在的集合,并和前面的合并,直到所有的集合都合并为一个集合

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second

const int N=1e5+10;

typedef pair<int,int> pii;
int fa[N];
pii goods[N];
int n;
int find(int x)
{
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void solve()
{
    rep(i,0,N+1) fa[i]=i;


    rep(i,1,n+1) cin>>goods[i].fi>>goods[i].se;
    sort(goods+1,goods+1+n);
    reverse(goods+1,goods+1+n);

    int ans=0;
    rep(i,1,n+1)
    {
        int id=find(goods[i].se);
        if(id>0)
        {
            fa[id]=id-1;
            ans+=goods[i].fi;
        }
    }
    cout<<ans<<endl;
}
int main()
{
    while(cin>>n) solve();
}
posted @ 2020-08-15 16:20  Hyx'  阅读(144)  评论(0编辑  收藏  举报