目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2、复杂度
3、代码详解
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
0打折 - 蓝桥云课 (lanqiao.cn)
二、解题报告
1、思路分析
思路很简单,按照时间顺序遍历,计算该天购买所有商品的总价格然后维护最小值
我们考虑对于一件物品在[l, r]内打折,等价于在第l天开始打折,第r+1天结束打折
那么我们可以用结构体存储如下信息:第 i 天,商品a调整价格为b
用平衡树维护每个商品当前有效价格集合
然后对于[l, r] 打折的商品<a, b>我们存两个结构体
第l天,商品a调整价格为b * p * / 100
第r + 1天,商品a 调整价格为 -1 - b * p * / 100
第一个很好理解,第二个并非是真的这样,而是我们遍历到该信息后得知商品a之前的价格没用了,我们用-1减去结构体内的价格就能得到之前的价格,我们从商品a的价格集合中删去即可
读入信息后,将结构体按时间升序排序,顺序遍历,每次处理一天内的所有信息
然后维护最小值即可
注意multiset如果erase(key)会将key都删掉,如果是erase(st.find(key))只会删除一个
2、复杂度
时间复杂度: O(nlogn)空间复杂度:O(n)
3、代码详解
#include <bits/stdc++.h>
using i64 = long long;
using PII = std::pair<int, int>;
const int N = 1e5 + 10, M = 8e5 + 10;
int n, m, tot;
struct node {
int s, w, id;
bool operator < (const node& x) const {
return s < x.s;
}
} q[M];
std::multiset<int> st[N];
int main () {
std::cin >> n >> m;
std::vector<int> w(n + 1, 1e9);
for (int i = 0, s, t, p, c; i < m; i ++ ) {
std::cin >> s >> t >> p >> c;
for (int j = 0, a, b; j < c; j ++ ) {
std::cin >> a >> b;
w[a] = std::min(w[a], b);
int x = 1LL * b * p / 100;
q[tot ++] = { s, x, a };
q[tot ++] = { t + 1, -x - 1, a };
}
}
for (int i = 1; i <= n; i ++ ) st[i].insert(w[i]);
std::sort(q, q + tot);
i64 ans = std::accumulate(w.begin() + 1, w.end(), 0LL);
i64 s = ans;
for (int i = 0; i < tot; ) {
int t = q[i].s;
while (i < tot && q[i].s == t) {
s -= *st[q[i].id].begin();
if (q[i].w < 0)
st[q[i].id].erase(st[q[i].id].find(-1 - q[i].w));
else
st[q[i].id].insert(q[i].w);
s += *st[q[i].id].begin();
i ++;
}
ans = std::min(ans, s);
}
std::cout << ans;
return 0;
}