题解:AT_abc292_h [ABC292Ex] Rating Estimator
首先可以把式子转换成
下面将
但是如果此时要查大于等于
此时有一个套路,对于一段原本不满足单调性的前缀取
于是可以线段树二分找到第一个下标
对于原序列,额外用一个树状数组维护动态前缀和。
写得有点丑,是
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 5;
int n, B, Q, c, x, a[N], pre[N];
namespace SGT {
#define mid (L + R) >> 1
#define son p, L, R
#define lson ls(p), L, (L + R) >> 1
#define rson rs(p), ((L + R) >> 1) + 1, R
struct Node {
int mx, pls;
} t[N << 2];
inline int ls(int p) {
return p << 1;
}
inline int rs(int p) {
return p << 1 | 1;
}
inline void psup(int p) {
t[p].mx = max(t[ls(p)].mx, t[rs(p)].mx);
return ;
}
inline void modify(int x, int k, int p = 1, int L = 1, int R = n) {
if(L == R) {
t[p].mx = k;
return ;
}
if(x <= mid) modify(x, k, lson);
else modify(x, k, rson);
psup(p);
}
inline void work(int p, int L, int R, int k) {
t[p].mx += k;
t[p].pls += k;
return ;
}
inline void psd(int p, int L, int R) {
if(! t[p].pls) return ;
work(lson, t[p].pls), work(rson, t[p].pls);
t[p].pls = 0;
return ;
}
inline void add(int l, int r, int k, int p = 1, int L = 1, int R = n) {
if(l <= L && R <= r) {
work(son, k);
return ;
}
psd(son);
if(l <= mid) add(l, r, k, lson);
if(r > mid) add(l, r, k, rson);
psup(p);
return ;
}
inline int ask(int l, int r, int p = 1, int L = 1, int R = n) {
int res = -1e18;
if(l <= L && R <= r) return t[p].mx;
psd(son);
if(l <= mid) res = max(res, ask(l, r, lson));
if(r > mid) res = max(res, ask(l, r, rson));
return res;
}
inline int binary() {
int l = 1, r = n, ans = n;
while(l <= r) {
int Mid = (l + r) >> 1;
if(ask(1, Mid) >= 0) ans = Mid, r = Mid - 1;
else l = Mid + 1;
}
return ans;
}
#undef mid
#undef son
#undef lson
#undef rson
}
using namespace SGT;
namespace BIT {
int t[N];
inline int lowbit(int x) {
return x & -x;
}
inline void Add(int x, int k) {
for( ; x <= n ; x += lowbit(x))
t[x] += k;
return ;
}
inline int Query(int x) {
int res = 0;
for( ; x ; x -= lowbit(x))
res += t[x];
return res;
}
}
using namespace BIT;
signed main() {
ios_base :: sync_with_stdio(NULL);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> B >> Q;
for(int i = 1 ; i <= n ; ++ i)
cin >> a[i], pre[i] = pre[i - 1] + a[i];
for(int i = 1 ; i <= n ; ++ i)
Add(i, a[i]), modify(i, pre[i] - i * B);
while(Q --) {
cin >> c >> x;
add(c, n, x - a[c]);
Add(c, x - a[c]);
a[c] = x;
int pos = binary();
cout << fixed << setprecision(20) << (Query(pos) * 1.0 / pos * 1.0) << '\n';
}
return 0;
}