inlinevoidadd(int p, ll x){ if (p == 0) return; while (p <= n) { tr[p] += x; p += lowbit(p); } }
inline ll query(int l, int r){ ll lres = 0, rres = 0; l -= 1; while (l > 0) { lres += tr[l]; l -= lowbit(l); } while (r > 0) { rres += tr[r]; r -= lowbit(r); } return rres - lres; }
inlineintfindkth(int k){ // 找到第k个元素,当然应当是要求只能出现0和1 int x = 0, sum = 0; for (int i = __lg(n); ~i; --i) { x += 1 << i; if (x >= n || sum + tr[x] >= k) { x -= 1 << i; } else { sum += tr[x]; } } return x + 1; // 我们始终让cx < k,所以返回的就是最大的比k小的,+1就是新元素出现的地方 }
inlineintkthspace(int k){ // 找到第k个空位,当然应当是要求只能出现0和1 int cx = 0; for (int i = 1 << 20; i > 0; i >>= 1) { // 这个你可以理解为不断缩小步长的搜索 if (cx + i <= n && lowbit(cx + i) - tr[cx + i] < k) { // lowbit(cx)-tr[cx+i] 表示cx+i这个树状数组区间有多少空位 k -= lowbit(cx + i) - tr[cx + i]; cx += i; } } return cx + 1; // 我们始终让cx < k,所以返回的就是最大的比k小的,+1就是新空位出现的地方 } };
structVal_id { ll val, id;
booloperator<(const Val_id &o) const { if (val != o.val) { return val < o.val; } return id < o.id; } };
// 在 k<=0 的时候返回 1 ll binpow(ll a, ll k, const ll &p = mod){ ll res = 1; a %= p; while (k > 0) { if ((k & 1) == 1) res = a * res % p; a = a * a % p; k >>= 1; } return res; }
voidSolve(){ ll N; cin >> N; vector<Val_id> A(N); for (int i = 0; i < N; ++i) { cin >> A[i].val; A[i].id = i + 1; } vector<Val_id> li_pos_to = A; A.insert(A.begin(),Val_id{}); sort(all(li_pos_to)); li_pos_to.insert(li_pos_to.begin(), Val_id{}); vector<ll> id_to_pos(N + 2); for (int i = 1; i <= N; ++i) { // 树状数组不能处理 0-based id_to_pos[li_pos_to[i].id] = i; } BIT tr(N); vector<ll> processing_pos = {0}; auto find_ans = [&](ll len) -> ll { ll l = 0, r = len - 1; auto cal_left = [&](ll ia) -> ll { ll pa = processing_pos[ia]; if (ia <= 2) { return0; } ll res = tr.query(1, processing_pos[ia - 2]); ll pb = processing_pos[ia - 1]; res = li_pos_to[pb].val * (ia - 2) - res; return res; }; auto cal_right = [&](ll ia) -> ll { if (ia >= len - 1) { return0; } ll pa = processing_pos[ia]; ll pb = processing_pos[ia + 1]; ll res = tr.query(processing_pos[ia + 2], N); res = res - li_pos_to[pb].val * (len - ia - 1); return res; }; auto check1 = [&](ll p) -> bool { // 这个程序,只要左边比右边大,就 return false returncal_left(p) >= cal_right(p); }; auto check2 = [&](ll p) -> bool { // 这个程序,只要左边比右边大,就 return false returncal_left(p) <= cal_right(p); }; while (l < r) { ll mid = l + r >> 1; if (check1(mid)) { r = mid; } else { l = mid + 1; } } ll ans1 = l; l = 1, r = len; while (l < r) { ll mid = l + r +1 >> 1; if (check2(mid)) { l = mid; } else { r = mid - 1; } } ll ans2=l; // #ifdef LOCAL // debug(ans1); // debug(ans2); // debug(cal_left(ans1)); // debug(cal_right(ans2)); // #endif ll res=min(max(cal_left(ans1),cal_right(ans1)),max(cal_right(ans2),cal_left(ans2))); res%=mod; res*=binpow(len-2,mod-2); res%=mod; return res; }; for (int i = 1; i <= N; ++i) { tr.add(id_to_pos[i], A[i].val); // processing_pos.push_back(id_to_pos[i]); processing_pos.insert(lower_bound(all(processing_pos), id_to_pos[i]), id_to_pos[i]); if (i <= 2) { continue; } ll res=find_ans(i); cout<<res<<"\n"; } }
signedmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifdef LOCAL cout.setf(ios::unitbuf); // 无缓冲流,方便我们调试 #endif
// cin >> lT; // for (testcase=1;testcase<=lT;++testcase) Solve(); return0; }