Codeforces Round 536 (Div. 2) (E)


layout: post
title: Codeforces Round 536 (Div. 2)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces
- DP
- 数据结构


传送门

前四题签到题不讲,

E.Lunar New Year and Red Envelopes (DP+数据结构)

题意

有k个红包,每个红包可以在一个时间段拿起,并且在拿起之后知道D时间都不能拿其他红包

如果在某一时刻可以拿红包会拿金额最大的,如果金额同样大会拿D最大的,

有m次干扰的机会,可以让在某一时刻不能拿红包。

问最少可以得到多少金额

题意

首先,每一时刻拿哪个红包和时间D都已经固定了,于是我们就直接构造dp转移一下就行
\[ dp[i][j]=在i时刻用了j次机会得到的最少金额 \]
那么对于一个时刻,如果没有红包那么就直接转移到下一时间
\[ dp[i+1][j]=min(dp[i+1][j],dp[i][j]); \]
如果可以抢红包那么,
\[ dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]) 被打扰 \]

\[ dp[d+1][j]=min(dp[d+1][j],dp[i][j]+w[i]);//不去打扰;dp[d+1][j]=min(dp[d+1][j],dp[i][j]+w[i]);//不去打扰 \]
然后这题的很多解法的DP都差不多,主要差别是如何获取每一时间的最优金额和D的,

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e5+20;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll dp[maxn][205];
int n,m,k;
struct node{
    int w,d;
    void add(int ww,int dd){
        if(ww>w)w=ww,d=dd;
        if(ww==w&&dd>d)d=dd;
    }
}my[maxn<<2];
void down(int i){
    my[i<<1].add(my[i].w,my[i].d);
    my[i<<1|1].add(my[i].w,my[i].d);
}
void update(int i,int l,int r,int ql,int qr,int w,int d){
    if(l>=ql&&r<=qr){
        my[i].add(w,d);
        return;
    }
    int mid=(l+r)/2;
    down(i);
    if(ql<=mid)update(i<<1,l,mid,ql,qr,w,d);
    if(qr>mid)update(i<<1|1,mid+1,r,ql,qr,w,d);
}
node query(int i,int l,int r,int pos){
    if(l==r){
        return my[i];
    }
    down(i);
    int mid=(l+r)/2;
    if(pos<=mid)query(i<<1,l,mid,pos);
    else query(i<<1|1,mid+1,r,pos);
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++){
        int s,t,d,w;
        cin>>s>>t>>d>>w;
        update(1,1,n,s,t,w,d);
    }
    memset(dp,inf,sizeof(dp));
    for(int i=0;i<=m;i++)dp[1][i]=0;
    for(int i=1;i<=n;i++){
        node now=query(1,1,n,i);
        int w=now.w;int d=now.d;
        for(int j=0;j<=m;j++){
            if(d){
                dp[d+1][j]=min(dp[d+1][j],dp[i][j]+w);
                dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]);
            }
            else
                dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
        }
    }
    ll ans=inf;
    for(int i=0;i<=m;i++)ans=min(ans,dp[n+1][i]);
    cout<<ans<<endl;
    return 0;
}
上一篇:JS实现倒计时(天数,时,分,秒)


下一篇:JUC常用类笔记