Cloud Computing 【CodeForces - 1070C】【线段树+思维】

题目链接


  题意:有这样连续的N天,每一天为了公司的运营,需要消耗的是K个CPU核心零件,我们有M个生产厂家,他们分别有这样的规则:在[l, r]这几天里工作,每天能捣鼓出最多C个零件,每个零件的售价是P元,问的是这N天最少需要消耗的金钱总数。

  思路:遇到这样的天数问题,又有多个条件,想到的就是利用差分的思想来存,在第L天的时候存入,第R+1天的时候取出,然后,我们可以看到价值的上限是1e6,这样我们不如直接去搜索区间内的前缀的最小价值,权值线段树来存,放入的是每个值的元素的个数,然后去查询前K大的所有的数的和。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e6 + 7;
const int _UP = 1e6;
int N, K, M;
vector<pair<ll, ll>> vt[maxN];
struct node
{
    ll num, price;
    node(ll a = 0, ll b = 0):num(a), price(b) {}
}tree[maxN<<2];
inline void pushup(int rt) { tree[rt] = node(tree[lsn].num + tree[rsn].num, tree[lsn].price + tree[rsn].price); }
void update(int rt, int l, int r, ll pos, ll val)
{
    if(l == r)
    {
        tree[rt].num += val;
        tree[rt].price += pos * val;
        return;
    }
    int mid = HalF;
    if(pos <= mid) update(Lson, pos, val);
    else update(Rson, pos, val);
    pushup(rt);
}
ll query(int rt, int l, int r, ll Kth)
{
    if(tree[rt].num <= Kth) return tree[rt].price;
    if(l == r) return l * Kth;
    int mid = HalF;
    if(tree[lsn].num >= Kth) return query(Lson, Kth);
    else return query(Rson, Kth - tree[lsn].num) + tree[lsn].price;
}
int main()
{
    scanf("%d%d%d", &N, &K, &M);
    for(int i=1, L, R, C, P; i<=M; i++)
    {
        scanf("%d%d%d%d", &L, &R, &C, &P);
        vt[L].push_back(MP(C, P));
        vt[R+1].push_back(MP(-C, P));
    }
    ll ans = 0;
    for(int i=1; i<=N; i++)
    {
        for(auto it : vt[i]) update(1, 1, _UP, it.second, it.first);
        ans += query(1, 1, _UP, K);
    }
    printf("%lld\n", ans);
    return 0;
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值