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.
The array is always a palindrome. Type 2 preserves it, and deleting the middle also preserves it. That symmetry is not decoration; it kills most of the problem.
Pair every subsequence with its mirrored subsequence. If the chosen values are , their two balances add to
So the final answer depends only on and the current length , not on positions. The huge array is basically fake intimidation.
The answer is Maintain , , and under updates.
The only annoying part is finding the deleted middle value. For every inserted value, keep a 4-state cycle: states mean “this insertion supplies the deleted value”, states mean “pass through to older insertions”. New inserts start at state if the old length was even, otherwise state .
The palindrome shortcut
First, notice the invariant: the array is always a palindrome.
That invariant is the whole reason this problem is not complete nonsense.
Take any non-empty subsequence of length , with values in chosen order Its balance is
Now mirror the chosen positions across the palindrome. The chosen values appear in reverse order: The mirrored balance is
Add them:
So
Since mirroring is a bijection on all subsequences, summing over all subsequences gives where:
Computing
Let
Each element appears in exactly subsequences, so
Computing
Fix one element . In subsequences of length , it appears in ways, and contributes to the average.
So its total coefficient in is
Use
Therefore
Thus
So the answer is
The statement guarantees on type 3 queries, so division by is legal modulo .
Maintaining the easy stuff
Maintain:
For type 2 with value :
For type 1, after removing value :
So the math part is tiny. The real trap is: what is ?
Finding the deleted middle value
Do not assume the newest inserted is the middle. That is just wrong. Example:
and the middle is still , not .
For every type 2 insertion, store its value and a state in .
Interpret the states like this:
Whenever a type 1 deletion touches an insertion, advance its state:
Now, what initial state should a new insertion get?
If the old length is even, the inserted goes exactly in the middle, so it should be deleted immediately. Start at state :
If the old length is odd, the old middle survives as the new middle, and the inserted appears for the next two deletions. Start at state :
For a type 1 query, scan insertions from newest to oldest:
This is amortized : the state machine behaves like a small carry chain, and over the whole query stream the total number of passed states is linear. No giant array, no cursed rope structure, no suffering for sport.
Complexity
Each query costs amortized except modular inverse on type 3, which costs .
Total complexity: with memory.
#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 ll INV2 = (MOD + 1) / 2;
ll norm(ll x) {
x %= MOD;
if (x < 0) x += MOD;
return x;
}
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
ll inv(ll x) {
return modPow(x, MOD - 2);
}
ll getDeleted(vector<pair<ll, int>>& added) {
for (int i = (int)added.size() - 1; i >= 0; --i) {
int state = added[i].second;
added[i].second = (state + 1) & 3;
if (state < 2) return added[i].first;
}
return 0;
}
int main() {
setIO();
int tc;
cin >> tc;
while (tc--) {
int q;
cin >> q;
ll len = 0;
ll sum = 0;
ll pow2Len = 1;
bool odd = false;
vector<pair<ll, int>> added;
added.reserve(q);
while (q--) {
int type;
cin >> type;
if (type == 1) {
ll v = getDeleted(added);
sum = norm(sum - v);
len = norm(len - 1);
pow2Len = pow2Len * INV2 % MOD;
odd = !odd;
} else if (type == 2) {
ll x;
cin >> x;
x %= MOD;
added.push_back({x, odd ? 3 : 1});
sum = (sum + (len + 1) % MOD * x) % MOD;
len = (2 * len + 1) % MOD;
pow2Len = 2 * pow2Len % MOD * pow2Len % MOD;
odd = true;
} else {
ll firstPart = pow2Len * INV2 % MOD;
ll secondPart = norm(pow2Len - 1) * inv(len) % MOD;
ll ans = sum * ((firstPart + secondPart) % MOD) % MOD * INV2 % MOD;
cout << ans << '\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 ll INV2 = (MOD + 1) / 2;
ll norm(ll x) {
x %= MOD;
if (x < 0) x += MOD;
return x;
}
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
ll inv(ll x) {
return modPow(x, MOD - 2);
}
ll getDeleted(vector<pair<ll, int>>& added) {
for (int i = (int)added.size() - 1; i >= 0; --i) {
int state = added[i].second;
added[i].second = (state + 1) & 3;
if (state < 2) return added[i].first;
}
return 0;
}
int main() {
setIO();
int tc;
cin >> tc;
while (tc--) {
int q;
cin >> q;
ll len = 0;
ll sum = 0;
ll pow2Len = 1;
bool odd = false;
vector<pair<ll, int>> added;
added.reserve(q);
while (q--) {
int type;
cin >> type;
if (type == 1) {
ll v = getDeleted(added);
sum = norm(sum - v);
len = norm(len - 1);
pow2Len = pow2Len * INV2 % MOD;
odd = !odd;
} else if (type == 2) {
ll x;
cin >> x;
x %= MOD;
added.push_back({x, odd ? 3 : 1});
sum = (sum + (len + 1) % MOD * x) % MOD;
len = (2 * len + 1) % MOD;
pow2Len = 2 * pow2Len % MOD * pow2Len % MOD;
odd = true;
} else {
ll firstPart = pow2Len * INV2 % MOD;
ll secondPart = norm(pow2Len - 1) * inv(len) % MOD;
ll ans = sum * ((firstPart + secondPart) % MOD) % MOD * INV2 % MOD;
cout << ans << '\n';
}
}
}
return 0;
}