CF1106E Lunar New Year and Red Envelopes

set预处理+DP

对于每一个时间点,记录开始于此时间的红包和结束于此时间的红包

那么在$O(n)$的复杂度就可以处理出每一个时间点的红包

然后将这些红包插入$set$中,以$w$为第一关键字,$d$为第二关键字排序

每次取出$set$中最大元素即是当前父亲要选的红包

现在Alice会打扰其父亲,所以记$dp[i][j]$表示第$i$个时间点前,Alice打扰了$j$次时,父亲取到钱的最小值

那么对于这道题来说填表法比较复杂,所以考虑刷表法

对于一个时间点Alice可以选择打扰或不打扰

如果打扰,$dp[i][j]$可以转移到$dp[i+d][j$],$d$为当前选择红包的$d$值

如果不打扰,$dp[i][j]$可以转移到$dp[i+1][j+1]$

#include <bits/stdc++.h>
#define ll long long
#define inf 1e18
using namespace std;
const ll MAXN=1e5+100;
ll n,m,k,dp[MAXN][210],mt;
struct node
{
    ll s,t,d,w,key;
}sh[MAXN];
vector <node> be[MAXN],ed[MAXN];
multiset <node> s;//需要用多重集合,考虑重复
bool operator < (node a,node b)
{
    return (a.w>b.w || a.w==b.w && a.d>b.d || a.w==b.w && a.d==b.d && a.key<b.key);
}
int main()
{
    srand(time(0));
    scanf("%lld%lld%lld",&n,&m,&k);
    for (ll i=1;i<=k;i++)
      scanf("%lld%lld%lld%lld",&sh[i].s,&sh[i].t,&sh[i].d,&sh[i].w);
    for (ll i=1;i<=k;i++)
      sh[i].key=rand();//表示随机选择
    for (ll i=1;i<=k;i++)
    {
        ed[sh[i].t].push_back(sh[i]);
        be[sh[i].s].push_back(sh[i]);//记录开始的红包和结束的红包
    }
    for (ll i=1;i<=n+1;i++)
    {
        for (ll j=0;j<=m;j++)
          dp[i][j]=inf;
    }
    dp[1][0]=0;//初始打扰次数为0
    for (ll i=1;i<=n;i++)
    {
        multiset <node> :: iterator it;
        for (ll j=0;j<(ll)ed[i-1].size();j++)
        {
            it=s.lower_bound(ed[i-1][j]);
            s.erase(it);
        }
        for (ll j=0;j<(ll)be[i].size();j++)
          s.insert(be[i][j]);
        if (s.empty())
        {
            for (ll j=0;j<=min(i-1,m);j++)
              dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
        }
        else
        {
            node g;
            g=*s.begin();
            for (ll j=0;j<=min(i-1,m);j++)
            {
                if (j!=m)//注意边界
                {
                    dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]);
                    dp[g.d+1][j]=min(dp[g.d+1][j],dp[i][j]+g.w);
                }
                else
                {
                    dp[g.d+1][j]=min(dp[g.d+1][j],dp[i][j]+g.w);
                }
            }
        }
    }
    ll ans=inf;
    for (ll i=0;i<=m;i++)
      ans=min(ans,dp[n+1][i]);
    printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/huangchenyan/p/11247364.html