NOIP2023模拟2联测23 C. 负责

27 篇文章 0 订阅

NOIP2023模拟2联测23 C. 负责

题目大意

给你 n n n 个区间 [ l i , r i ] [l_i , r_i] [li,ri] ,每个区间有个 w i w_i wi 。如果两个区间有交集(包括端点)那么两个区间就可以连边,形成一个图。

现在需要你删除一些区间,使得每个区间大小不超过 k k k 。问最小删除的区间权值和。

思路

显然,想要断开一个连通块,那就是要把包含某个点的区间全部删掉。

d p i dp_i dpi 表示只考虑在 r i r_i ri 之前的区间,且 r i r_i ri 是最后一个断开的地方的最大选的区间的权值和。

每次向后更新时加上区间的权值,如果区间个数大于 k k k 就把权值最小的区间删掉,用一个堆维护。

时间复杂度 O ( n 2 l o g 2 n ) O(n^2log_2n) O(n2log2n)

code

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)
#define LL long long
using namespace std;
const int N = 2505;
int n , k , b[N] , f[N];
LL sum , ans , dp[N];
struct Re {
    int l , r;
    LL w;
} re[N];
priority_queue<LL , vector<LL> , greater<LL>> q;
bool cmp (Re x , Re y) { return x.r != y.r ? x.r < y.r : x.l < y.l; }
int main () {
    scanf ("%d%d" , &n , &k);
    fu (i , 1 , n) {
        scanf ("%d%d%lld" , &re[i].l , &re[i].r , &re[i].w);
        sum += re[i].w;
    }
    sort (re + 1 , re + n + 1 , cmp);
    LL now;
    fu (i , 0 , n) {
        ans = max (ans , dp[i]);
        now = 0;
        while (!q.empty ())
            q.pop ();
        fu (j , i + 1 , n) {
            if (re[i].r < re[j].l) {
                now += re[j].w;
                q.push (re[j].w);
                if (q.size () > k) {
                    now -= q.top ();
                    q.pop ();
                }
            }
            dp[j] = max (dp[j] , ans + now);
        }
    }
    printf ("%lld" , sum - ans);
    return 0;
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值