cf1070 C. Cloud Computing(线段树)

题意:

有m家店,第 \(i\) 家店只在第 \(l_i\) 天到第 \(r_i\) 天之间开业,每个core卖 \(p_i\) 元,每天最多售出 \(c_i\) 个core(但也可以售出0个、1个等,不超过 \(c_i\) 就行)。在1~n天里,你每天要买k个core,如果当天所有店全买了也不够k个,那就全买。求最小花费。

m <= 1e5,其他范围都是1e6,值域也是1e6

思路:

对价格建线段树,节点 l,r,cnt,cost 表示当前市面上价格大于等于l且小于等于r的所有core有几个,全买下来的花费是多少。

顺序处理每一天,如果今天有店加入就更新线段树,把今天新开的店的core加上,把今天关门的店的core减去,然后查询今天买k个core要多少钱。

只需单点增加和一个十分简单的查询。不用pushdown

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 5;
int n, k, m, w[N];
ll ans;
struct node {
    int l, r; ll cnt, cost;
} tr[N*4];
void pushup(int u)
{ //pushup很简单,就直接加
    tr[u].cnt = tr[u<<1].cnt + tr[u<<1|1].cnt;
    tr[u].cost = tr[u<<1].cost + tr[u<<1|1].cost;
}
void build(int u, int l, int r)
{ //全是0的线段树,初始化每个节点管哪个区间就行了
    if(l == r) tr[u] = {l, r};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u<<1, l, mid), build(u<<1|1, mid+1, r);
    }
}
void modify(int u, int p, ll d) //单点加(在位置p加上d)
{
    if(tr[u].l == tr[u].r)
        tr[u].cnt += d, tr[u].cost += p * d;
    else { //modify的else一般都没什么要改的
        int mid = tr[u].l + tr[u].r >> 1;
        if(p <= mid) modify(u<<1, p, d);
        if(p > mid) modify(u<<1|1, p, d);
        pushup(u);
    }
}
void query(int u, int k) //拼出k个,并更新答案
{ //我的写法保证当前k总不大于当前节点的cnt
    if(k == 0) return;
    else if(tr[u].l == tr[u].r) ans += tr[u].cost / tr[u].cnt * k; //叶子
    else if(k >= tr[u<<1].cnt)
        ans += tr[u<<1].cost, query(u<<1|1, k - tr[u<<1].cnt);
    else query(u<<1, k);
}

vector<pair<int,int>> ve[N]; //别写成vec套vec
signed main()
{
    scanf("%d%d%d", &n, &k, &m);
    while(m--) {
        int l, r, c, p; scanf("%d%d%d%d", &l, &r, &c, &p);
        ve[l].push_back({p,c}); ve[r+1].push_back({p,-c});
    }

    build(1, 1, 1000000);

    for(int i = 1; i <= n; i++) {
        for(auto [p, c] : ve[i]) modify(1, p, c);
        if(k >= tr[1].cnt) ans += tr[1].cost; //大于就全买了
        else query(1, k);
    }

    printf("%lld", ans);

    return 0;
}

posted @ 2021-12-30 23:01  Bellala  阅读(40)  评论(0)    收藏  举报