长沙现场赛A题

来源:互联网 发布:unity3d粒子系统教程 编辑:程序博客网 时间:2024/05/01 18:27

题目大意

Hint:虽然是最水的题,但是现场赛我们没有过,让我感觉非常捉急,所以现在我把这道题我的解法挂出来……话说我并没有参与A题……
题目大意就有一种东西,当你买不少于si件的时候,需要付pi的单价,现在给定所有的s和p,然后每次告诉你买多少件,问最少花多少钱。题目保证s逐级递增,p逐级递减。

解题思路

既然题目已经保证了随着s的递增,pi是递减的,那么这道题的策略就少了,对于每一个询问q,我们不可能把它分成几部分来买,因为那样每一部分都会多花钱,那么只有两种策略,一种是在当前它所在区间的价格下买正好的,一种是买比它多的,但是单价少总价会省钱的,现在问题就是如何确定用什么样的策略。
首先,这道题相当于告诉我们,对于每一种东西,如果多买,我们一定恰好买某一个si件,因为如果多买就会多花钱,那么就简单了,在他多买的情况下,我们可以得到他多买的所有的情况,在这所有的情况里面求一个最小值,与买正好的对比一下就可以了……
对于最小值,有很多种处理方式,写一个RMQ,线性预处理,或者像我这种只会用线段树写的……

参考代码

#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1typedef long long LL;const int maxn = (int)1e5 + 10;const long long INF = (LL)1 << 62;LL s[maxn], p[maxn], mi[maxn << 2];void PushUp(int rt){    mi[rt] = min(mi[rt << 1], mi[rt << 1 | 1]);}void build(int l, int r, int rt){    if (l == r){        mi[rt] = s[l] * p[l];        return;    }    int m = (l + r) >> 1;    build(lson);    build(rson);    PushUp(rt);}LL query(int ll, int rr, int l, int r, int rt){    if (ll <= l && rr >= r) return mi[rt];    int m = (l + r) >> 1;    LL ret = INF;    if (ll <= m) ret = min(ret, query(ll, rr, lson));    if (rr > m) ret = min(ret, query(ll, rr, rson));    return ret;}int n, m;void solve(){    scanf("%d%d", &n, &m);    for (int i = 1; i <= n; i++) scanf("%lld%lld", &s[i], &p[i]);    build(1, n, 1);    while(m--){        int x; scanf("%d", &x);        int pos = lower_bound(s, s + n, x) - s;        if (s[pos] > x) pos -= 1;        LL x1 = query(pos + 1, n, 1, n, 1);        LL x2 = x * p[pos];        LL ans = x1 > x2 ? x2 : x1;        printf("%lld\n", ans);    }}int main(){    int cs; scanf("%d", &cs);    while(cs--) solve();    return 0;}


原创粉丝点击