Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Stop thinking about physical blocks first. Store slider as . The strict positions become a nondecreasing array , because the mandatory 1-cell spacing has been subtracted away.
An operation has target . In the array it does this: all become [0m\min(b_j,y), becomes , and all become . The direction casework basically disappears. Nice.
Now fix one slider . Every operation is just one scalar operation on : if its index is left of , it is ; if it is exactly , it is assignment; if it is right of , it is .
For a fixed threshold , look only at the bit . Some operations force it to true, some force it to false, and the rest do nothing. In a random permutation, the final bit is decided by the latest forcing operation.
For slider and threshold , true-forcers are operations with index and ; false-forcers are operations with index and . So when . Sweep over operation target values and sum these probabilities.
The permutations look terrifying, but the monster is fake. The trick is to stop simulating sliders and start asking threshold questions.
Let the actual position of slider be . Define
.
Because , the array is nondecreasing. Also every value lies in . Let
.
For an operation , define its compressed target as
.
Now look at what this operation does to .
If slider moves right, then every slider to its right that is too far left gets pushed until its compressed value is at least . If it moves left, every slider to its left that is too far right gets pushed until its compressed value is at most .
Because is sorted, both cases combine into one clean formula:
That is the first big simplification. The slider physics was just a dramatic way to say prefix-min, point-assign, suffix-max.
Now fix a slider . We only care about the scalar value .
Each operation acts on this scalar as:
A direct expected value DP over these max/min/assign operations is annoying. Max and min do not commute; trying to average them directly is where solutions go to die.
So do not average the value directly. Average its bits by threshold.
For an integer value in ,
.
So if we can compute for every useful threshold , we can sum those probabilities to get the expected compressed position.
Fix slider and threshold . Track the boolean
.
Now classify an operation :
So the true-forcing operations are exactly:
and the false-forcing operations are exactly:
.
Let
number of true-forcers,
number of false-forcers.
If , no operation ever touches this threshold bit, so it stays equal to the initial value .
Otherwise, in a uniformly random permutation, the last forcing operation is uniformly distributed among those forcing operations. If the latest one is a true-forcer, the final bit is true; if it is a false-forcer, the final bit is false. Irrelevant operations after it do nothing to this bit.
Therefore
when .
That is the whole combinatorics trick. No factorial explosion, no cursed permutation DP.
For fixed , the values and only change when passes some operation target .
An operation with target contributes:
So sort all operations by , then sweep threshold intervals. On an interval where no target is crossed, and are constant, so the probability is constant too. Add interval length times that probability.
If on an interval, add only the part of the interval where the initial is at least .
This gives the expected compressed final value of slider modulo .
Finally, actual position is , and the answer asks for the sum over all permutations, so multiply the expected position by .
For each slider, we scan the sorted operation targets once. That is per test case after sorting, with memory. Since the total and total are both at most , this is comfortably fine.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll MOD = 1000000007LL;
const int MAXQ = 5000;
ll modPow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
struct Op {
int idx;
ll y;
};
int main() {
setIO();
vector<ll> fact(MAXQ + 1), inv(MAXQ + 1);
fact[0] = 1;
for (int i = 1; i <= MAXQ; i++) fact[i] = fact[i - 1] * i % MOD;
for (int i = 1; i <= MAXQ; i++) inv[i] = modPow(i, MOD - 2);
int T;
cin >> T;
while (T--) {
int n, q;
ll m;
cin >> n >> m >> q;
ll M = m - n;
vector<ll> b(n + 1);
for (int i = 1; i <= n; i++) {
ll a;
cin >> a;
b[i] = a - i;
}
vector<Op> ops(q);
for (int j = 0; j < q; j++) {
int i;
ll x;
cin >> i >> x;
ops[j] = {i, x - i};
}
vector<Op> byY = ops;
sort(byY.begin(), byY.end(), [](const Op& a, const Op& b) {
return a.y < b.y;
});
vector<ll> ans(n + 1);
for (int k = 1; k <= n; k++) {
int A = 0, C = 0;
for (const Op& op : ops) {
if (op.idx <= k && op.y >= 1) A++;
if (op.idx >= k && op.y < 1) C++;
}
int ptr = 0;
while (ptr < q && byY[ptr].y < 1) ptr++;
ll expected = 0;
ll cur = 1;
while (cur <= M) {
ll nxt = M + 1;
if (ptr < q) nxt = min(M + 1, byY[ptr].y + 1);
ll r = nxt - 1;
if (cur <= r) {
ll len = (r - cur + 1) % MOD;
int den = A + C;
if (den > 0) {
expected = (expected + len * A % MOD * inv[den]) % MOD;
} else {
ll upto = min(r, b[k]);
if (upto >= cur) {
expected = (expected + (upto - cur + 1) % MOD) % MOD;
}
}
}
cur = nxt;
while (ptr < q && byY[ptr].y + 1 == cur) {
if (byY[ptr].idx <= k) A--;
if (byY[ptr].idx >= k) C++;
ptr++;
}
}
ans[k] = fact[q] * ((expected + k) % MOD) % MOD;
}
for (int i = 1; i <= n; i++) {
if (i > 1) cout << ' ';
cout << ans[i];
}
cout << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll MOD = 1000000007LL;
const int MAXQ = 5000;
ll modPow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
struct Op {
int idx;
ll y;
};
int main() {
setIO();
vector<ll> fact(MAXQ + 1), inv(MAXQ + 1);
fact[0] = 1;
for (int i = 1; i <= MAXQ; i++) fact[i] = fact[i - 1] * i % MOD;
for (int i = 1; i <= MAXQ; i++) inv[i] = modPow(i, MOD - 2);
int T;
cin >> T;
while (T--) {
int n, q;
ll m;
cin >> n >> m >> q;
ll M = m - n;
vector<ll> b(n + 1);
for (int i = 1; i <= n; i++) {
ll a;
cin >> a;
b[i] = a - i;
}
vector<Op> ops(q);
for (int j = 0; j < q; j++) {
int i;
ll x;
cin >> i >> x;
ops[j] = {i, x - i};
}
vector<Op> byY = ops;
sort(byY.begin(), byY.end(), [](const Op& a, const Op& b) {
return a.y < b.y;
});
vector<ll> ans(n + 1);
for (int k = 1; k <= n; k++) {
int A = 0, C = 0;
for (const Op& op : ops) {
if (op.idx <= k && op.y >= 1) A++;
if (op.idx >= k && op.y < 1) C++;
}
int ptr = 0;
while (ptr < q && byY[ptr].y < 1) ptr++;
ll expected = 0;
ll cur = 1;
while (cur <= M) {
ll nxt = M + 1;
if (ptr < q) nxt = min(M + 1, byY[ptr].y + 1);
ll r = nxt - 1;
if (cur <= r) {
ll len = (r - cur + 1) % MOD;
int den = A + C;
if (den > 0) {
expected = (expected + len * A % MOD * inv[den]) % MOD;
} else {
ll upto = min(r, b[k]);
if (upto >= cur) {
expected = (expected + (upto - cur + 1) % MOD) % MOD;
}
}
}
cur = nxt;
while (ptr < q && byY[ptr].y + 1 == cur) {
if (byY[ptr].idx <= k) A--;
if (byY[ptr].idx >= k) C++;
ptr++;
}
}
ans[k] = fact[q] * ((expected + k) % MOD) % MOD;
}
for (int i = 1; i <= n; i++) {
if (i > 1) cout << ' ';
cout << ans[i];
}
cout << '\n';
}
return 0;
}