CF431E Chemistry Experiment 题解

权值线段树。

finally let's find the minimum among counted maximums.

最大值最小。二分。设当前二分中点为 $k$。

容易发现 $h_i\le k$ 的试管才会造成贡献,若 $\sum\limits_{h_i\le k}k-h_i\ge v$ 则 $k$ 合法。

$\sum\limits_{h_i\le k}k-h_i=\sum\limits_{h_i\le k}k-\sum\limits_{h_i\le k}h_i$。分别用权值线段树维护即可。

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
struct T
{
    T *l = 0, *r = 0;
    int c = 0;long long s = 0;
    void u()
    {
        c = s = 0;
        if(l) c += l->c, s += l->s;
        if(r) c += r->c, s += r->s;
    }
}*r;
void M(int l, int x, int y, int s, int t, T *&p)
{
    if(!p) p = new T;if(s == t) return (void)(p->c += x, p->s += y);int m = s + t
    >> 1;if(l <= m) M(l, x, y, s, m, p->l);else M(l, x, y, m + 1, t, p->r);p->u();
}
int X(int l, int r, int s, int t, T *p)
{
    if(!p) return 0;if(l <= s && t <= r) return p->c;int m = s + t >> 1, q = 0;if(l
    <= m) q += X(l, r, s, m, p->l);if(r > m) q += X(l, r, m + 1, t, p->r);return q;
}
long long Y(int l, int r, int s, int t, T *p)
{
    if(!p) return 0;if(l <= s && t <= r) return p->s;int m = s + t >> 1;long long q = 0;
    if(l <= m) q += Y(l, r, s, m, p->l);if(r > m) q += Y(l, r, m + 1, t, p->r);return q;
}
int n, m, a[100050];long long x;double L, R, K;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1;i <= n;++i)
        scanf("%d", a + i), M(a[i], 1, a[i], 0, 1e9, r);
    for(int i = 0, o;i < m;++i)
    {
        scanf("%d%lld", &o, &x);
        if(o & 1) M(a[x], -1, -a[x], 0, 1e9, r), scanf("%d", a + x), M(a[x], 1, a[x], 0, 1e9, r);
        else
        {
            L = 0;R = 1e11;while(fabs(L - R) > 1e-5){K = (L + R) / 2;
            if(K * X(0, min(K, 1e9), 0, 1e9, r) - Y(0, min(K, 1e9), 0, 1e9, r) >= x)
            R = K;else L = K;}printf("%.5lf\n", L);
        }
    }
}
posted @ 2023-03-20 08:23  5k_sync_closer  阅读(8)  评论(0编辑  收藏  举报  来源