码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #536 (Div. 2) E dp + set

时间:2019-03-30 21:37:20      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:using   href   end   begin   std   namespace   contest   eof   amp   

https://codeforces.com/contest/1106/problem/E

题意

一共有k个红包,每个红包在\([s_i,t_i]\)时间可以领取,假如领取了第i个红包,那么在\(d_i\)后才能领取下一个红包,每个红包价值\(w_i\),对方假如有机会领取红包他一定会领取,你有m次阻止对方领取的机会,问对方最少可以拿到多少红包

题解

  • 定义dp[i][j]为前i秒用了j次机会让对方拿到最小价值的红包
  • \(dp[i][j] - > dp[i+1][j+1]\) 假如使用阻止
  • \(dp[i][j] - > dp[d[s]+1][j]\) 假如不用
  • \(dp[i][j] - > dp[i+1][j]\) 这一秒没有可以领的红包
  • 用set处理当前第i秒可以领的优先级最高的红包

代码

#include<bits/stdc++.h>
#define pii pair<int,int>
#define MAXN 100005
#define mk make_pair
#define inf 0x3f3f3f3f
#define ll long long 
#define ft first
#define se second
using namespace std;
vector<pii>in[MAXN],out[MAXN];
multiset<pii>S;
int n,m,k,i,j,s,t,d,w;
ll dp[MAXN][205];
int main(){
    cin>>n>>m>>k;
    for(i=0;i<k;i++){
        scanf("%d%d%d%d",&s,&t,&d,&w);
        in[s].push_back(mk(w,d));
        out[t+1].push_back(mk(w,d));
    }
    memset(dp,inf,sizeof(dp));
    for(i=0;i<=m;i++)dp[1][i]=0;
    for(i=0;i<=n;i++){
        for(auto x:in[i])S.insert(x);
        for(auto x:out[i])S.erase(S.find(x));
        for(j=0;j<=m;j++){
            auto p=S.begin();
            if(p==S.end())
            dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
            else{
            p=S.end();p--;
            dp[p->se+1][j]=min(dp[i][j]+p->ft,dp[p->se+1][j]);
            dp[i+1][j+1]=min(dp[i][j],dp[i+1][j+1]);
            }
        }
    }
    cout<<dp[n+1][m];
}

Codeforces Round #536 (Div. 2) E dp + set

标签:using   href   end   begin   std   namespace   contest   eof   amp   

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10628982.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!