天天看點

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

Description

click me

Solution

考慮建 maxd m a x d 棵主席樹,儲存各個價位的果汁的分布。

考慮二分美味度,每次在主席樹上查一下就行了。

Code

/************************************************
 * Au: Hany01
 * Date: 
 * Prob: [BZOJ5343][LOJ2555] 混合果汁
 * Email: hany[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,  : ; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b,  : ; }

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

const int maxn = ;

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 * ];

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 * l * 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 + , r, x, dt);
    maintain(now);
    return now;
}

LL query(int rt1, int rt2, int l, int r, LL V)
{
    if (!V) return ;
    if (tr[rt2].suml - tr[rt1].suml < V) return l;
    if (l == r) return V * l * 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 + , 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, , n) J[i].d = read(), chkmax(maxp, J[i].p = read()), J[i].l = read();
    sort(J + , J +  + n), maxd = J[n].d;

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

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

    return ;
}
//水滿有時觀下鹭,草深無處不鳴蛙。
//    -- 陸遊《幽居初夏》