题目链接
题意:有这样连续的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;
}