线段树上二分模板
板子链接:Ex - Rating Estimator
洛谷链接:AT_abc292_h [ABC292Ex] Rating Estimator - 洛谷
误区:
对原式进行数学变形(这里a[i]就是p[i])
令
求
在数学上是成立的,但b[i]不满足单调性,故无法直接二分。
分析:
我们可以用线段树维护b数组的前缀最大值,然后找到第一个≥0的i即可。
实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500005;
int n, b, q, a[N], s[N];
struct sgt{struct node{int lzy, res; //tag和最大值}tr[N << 2];void pushup(int u){tr[u].res = max(tr[u << 1].res, tr[u << 1 | 1].res);}void build(int u, int l, int r){if(l == r){tr[u].res = s[l];return;}int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);pushup(u);}void maketag(int u, int v){tr[u].res += v;tr[u].lzy += v;}void pushdown(int u){if(!tr[u].lzy) return;maketag(u << 1, tr[u].lzy);maketag(u << 1 | 1, tr[u].lzy);tr[u].lzy = 0;}void modify(int u, int l, int r, int L, int R, int v){if(l >= L && r <= R){maketag(u, v);return;}int mid = l + r >> 1;pushdown(u);if(L <= mid) modify(u << 1, l, mid, L, R, v);if(R > mid) modify(u << 1 | 1, mid + 1, r, L, R, v);pushup(u);}pair<int, int> qry(int u, int l, int r){if(tr[u].res < 0) return {-1, -1};if(l == r) return {l, tr[u].res};int mid = l + r >> 1;pushdown(u);auto res = qry(u << 1, l, mid);if(res.first != -1) return res;return qry(u << 1 | 1, mid + 1, r);}
}T;
signed main(){ios::sync_with_stdio(0);cin.tie(0);cin >> n >> b >> q;int cur = 0;for(int i = 1; i <= n; i++){cin >> a[i];cur += a[i];s[i] = s[i - 1] + a[i] - b;}T.build(1, 1, n);while(q--){int c, x;cin >> c >> x;cur += x - a[c];T.modify(1, 1, n, c, n, x - a[c]);a[c] = x;auto pos = T.qry(1, 1, n);cout << fixed << setprecision(15);if(pos.first == -1) cout << 1.0 * cur / n << '\n';else cout << (1.0 * pos.second / pos.first) + b << '\n';}return 0;
}
防烫:只要你的输出与真值的绝对误差或相对误差不超过,就会被判定为正确。