Kabaleo Lite
Kabaleo Lite
https://ac.nowcoder.com/acm/contest/5673/K
题意
就是有n道菜,a[i]是每道菜可以赚的钱,−10^9≤ ai ≤10^9,b[i]是这道菜的个数,你每次只能选从1开始连续的菜,每份菜都选一个,然后问最多有多少顾客,并且顾客最多的前提下赚的钱最多是多少。
题解
先前缀和预处理一下,算一下从第1个到第i个都选一个的收益是多少。算完之后,我们按照sum[i]从大到小进行一个排序,然后按顺序进行选取,能选就选,不能就算了。我们用线段树维护一下[1,i]中b[i]的最小值,然后选取的时候修改一下区间[1,i]就好了,那么sum[i] * min(1 <= j <= i){b[j]}就是对于sum[i]的贡献。显然能服务多少个顾客是由b[1]决定的。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
typedef long long LL;
LL sum[N]; int b[N];
#define rs (k << 1 | 1)
#define ls (k << 1)
struct Node {
int id; LL val;
friend bool operator<(Node x, Node y) {
if (x.val == y.val) return x.id < y.id;
return x.val > y.val;
}
}a[N];
struct Tree {
int l, r, dat, add;
}tree[N << 2];
void pushUp(int k) {
tree[k].dat = min(tree[ls].dat, tree[rs].dat);
}
void build(int k, int l, int r) {
tree[k].l = l; tree[k].r = r;
tree[k].dat = 1e9;
tree[k].add = 0;
if (l == r) {
tree[k].dat = b[l];
return;
}
int m = (l + r) >> 1;
build(ls, l, m);
build(rs, m + 1, r);
pushUp(k);
}
void pushDown(int k) {
if (tree[k].add) {
tree[ls].add += tree[k].add;
tree[rs].add += tree[k].add;
tree[ls].dat += tree[k].add;
tree[rs].dat += tree[k].add;
tree[k].add = 0;
}
}
void change(int k, int x, int y, int val) {
if (x <= tree[k].l && tree[k].r <= y) {
tree[k].dat += val;
tree[k].add += val;
return;
}
pushDown(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (x <= m) change(ls, x, y, val);
if (y > m) change(rs, x, y, val);
pushUp(k);
}
int ask(int k, int x, int y) {
if (x <= tree[k].l && tree[k].r <= y) return tree[k].dat;
pushDown(k);
int m = (tree[k].l + tree[k].r) >> 1, ans = 1e9;
if (x <= m) ans = min(ans, ask(ls, x, y));
if (y > m) ans = min(ans, ask(rs, x, y));
return ans;
}
inline void print(__int128 x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) {
print(x / 10);
}
putchar(x % 10 + '0');
}
void solve(int cas) {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &sum[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
}
build(1, 1, n);
for (int i = 1; i <= n; i++) {
sum[i] += sum[i - 1];
}
for (int i = 1; i <= n; i++) a[i].id = i, a[i].val = sum[i];
sort(a + 1, a + 1 + n);
__int128 ans = 0;
for (int i = 1; i <= n; i++) {
int minn = ask(1, 1, a[i].id);
ans += (__int128)a[i].val * minn;
change(1, 1, a[i].id, -minn);
}
printf("Case #%d: %lld ", cas, b[1]);
print(ans);
printf("\n");
}
int main() {
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++) solve(cas);
return 0;
}
查看8道真题和解析
