【BZOJ5343】【LOJ2555】【CTSC2018】混合果汁(主席树,二分)

Description

click me


Solution

考虑建 m a x d 棵主席树,保存各个价位的果汁的分布。
考虑二分美味度,每次在主席树上查一下就行了。


Code

/************************************************
 * Au: Hany01
 * Date: 
 * Prob: [BZOJ5343][LOJ2555] 混合果汁
 * Email: [email protected]
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read()
{
    register int _, __; register char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 100005;

struct Juice
{
    int d, p, l;
    bool operator < (const Juice& A) const { return d < A.d; }
}J[maxn];

struct Node
{
    int lc, rc;
    LL suml, sump;
}tr[maxn * 40];

int n, rt[maxn], maxp, maxd, cnt;

#define mid ((l + r) >> 1)

inline void maintain(int u) {
    tr[u].suml = tr[tr[u].lc].suml + tr[tr[u].rc].suml, tr[u].sump = tr[tr[u].lc].sump + tr[tr[u].rc].sump;
}

int update(int las, int l, int r, int x, int dt)
{
    int now = ++ cnt;
    tr[now] = tr[las];
    if (l == r) {
        tr[now].suml += dt, tr[now].sump += dt * 1ll * x;
        return now;
    }
    if (x <= mid) tr[now].lc = update(tr[las].lc, l, mid, x, dt);
    else tr[now].rc = update(tr[las].rc, mid + 1, r, x, dt);
    maintain(now);
    return now;
}

LL query(int rt1, int rt2, int l, int r, LL V)
{
    if (!V) return 0;
    if (tr[rt2].suml - tr[rt1].suml < V) return 1000000000000000000ll;
    if (l == r) return V * 1ll * l;
    if (tr[tr[rt2].lc].suml - tr[tr[rt1].lc].suml <= V)
        return tr[tr[rt2].lc].sump - tr[tr[rt1].lc].sump +
            query(tr[rt1].rc, tr[rt2].rc, mid + 1, r, V - (tr[tr[rt2].lc].suml - tr[tr[rt1].lc].suml));
    else
        return query(tr[rt1].lc, tr[rt2].lc, l, mid, V);
}

int main()
{
#ifdef hany01
    File("bzoj5343");
#endif

    n = read();
    static int m = read();
    For(i, 1, n) J[i].d = read(), chkmax(maxp, J[i].p = read()), J[i].l = read();
    sort(J + 1, J + 1 + n), maxd = J[n].d;

    For(i, 1, n)
        if (J[i - 1].d == J[i].d) rt[J[i].d] = update(rt[J[i].d], 1, maxp, J[i].p, J[i].l);
        else {
            For(j, J[i - 1].d + 1, J[i].d - 1) rt[j] = rt[j - 1];
            rt[J[i].d] = update(rt[J[i].d - 1], 1, maxp, J[i].p, J[i].l);
        }

    for (; m--; )
    {
        register int L = 1, R = maxd, M;
        register LL V, g; scanf("%lld%lld", &g, &V);
        if (V > tr[rt[maxd]].suml || query(rt[0], rt[maxd], 1, maxp, V) > g) { puts("-1"); continue; }
        while (L < R) {
            M = (L + R + 1) >> 1;
            if (query(rt[M - 1], rt[maxd], 1, maxp, V) > g) R = M - 1; else L = M;
        }
        printf("%d\n", L);
    }

    return 0;
}
//水满有时观下鹭,草深无处不鸣蛙。
//    -- 陆游《幽居初夏》

猜你喜欢

转载自blog.csdn.net/hhaannyyii/article/details/80449332