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);
}
}
}