Below is a timeline of the changes made to the round from start to finish. I hope this can depict what setting a contest is actually like for aspiring problemsetters. Please give me feedback about this in the comments. What else about the round would you like to know? Was this helpful?
To denote problems, I will use quotes to denote the number of problems proposed for that postion so far (e.g. A' represents the first A proposed for the round, A'' represents second A proposed, etc). If the problem is in the final set, then it will be bolded. For dates, I will use the american standard notation (mm/dd).
Also, I will not go in detail about why problems were rejected/unused because they might appear in the future.
8/11: Codeforces Round 965 (Div. 2) has just concluded and sum has shipped himself off to college and won't have time due to attending frat parties his studies. I invite vgoofficial to problemset with me. We decide to get cooking straight away.
8/12: vgoofficial proposes D'. Gets accepted.
8/13: vgoofficial proposes E'. Problem accepted for backup.
8/14: vgoofficial proposes D''. Problem accepted for backup.
8/19: vgoofficial proposes E'', F' and G'. Both gets accepted for main set at the time. Seriously, bro just became the new BledDest.
8/21: We got bored and decided to focus on Codeforces Round 971 (Div. 4). Due to difficulty issues, we transfered problem E from that contest to problem B1 and B2 for this contest. B2 ultimately became D :)
8/22: vgoofficial proposes B', but satyam343 buffs it into F instead. Somewhere along the lines I also came up with A' and B'', both getting initially accepted.
8/23: Round gets put up for testing with 7 problems.
8/25: I came up with an idea for D'''. Also, vgoofficial proposes C, but initially gets ignored lmao.
8/26: satyam343 modifies B'' into D''''. Later, I also propose E''''.
8/28: satyam343 tries to modifies B'' again into C''. sum wakes up from his slumber and proposes F''.
8/29: I propose A''.
8/31: vgoofficial proposes D''''' and gets accepted.
9/2: satyam343 buffs D''' and it became NOTEQUALTREE.
9/6: vgoofficial and satyam343 modifies D' and it becomes G (G1). Later, A_G solved it in subquadratic, and it became G2.
9/9: I modify B'' into D''''''.
9/11: satyam343 modifies B'' into D'''''''. We hold a poll in our testing server to choose the victor among D'''''' and D'''''''.
9/12: I invent and propose C''', but wasn't accepted. satyam343 modifies B'' into D'''''''', but unused due to difficulty issues.
9/14: I invent and propose D''''''''', which was unused due to difficulty issues. Later that night, the aforementioned poll concludes, crowning D'''''' with 7 votes to 2. However, both candidates had difficulty issues so we still decided against using any of them (essentially we polled for nothing).
9/15: vgoofficial proposes B'''' and gets initially accepted, however, was later rejected.
9/17: I propose A''' but it wasn't great.
9/20: vgoofficial brings C up again and it gets prepared.
9/23: satyam343 modifies B'' into D'''''''''', but as the original author of B'', I didn't like it.
9/24: satyam343 modifies D''''''''' into D''''''''''', and it gets prepared.
9/28: vgoofficial modifies a unused problem I proposed for Codeforces Round 965 (Div. 2) into A'''', but unused due to difficulty issues.
9/30: vgoofficial proposes and prepares B. Later that night, satyam343 has conflicting thoughts whether to replace D''''''''''' yet again, but I held him at gunpoint to accept the problem spent 30 minutes convincing him that it is a good problem. This problem became E. For those of you who enjoyed the problem, you're welcome lmao.
10/02 — 10/17: Final testing and preparation.
10/13: vgoofficial proposes current A.
Please check out this amazing animated video tutorial by one of our beloved testers redpanda!!!
2030A - A Gift From Orangutan
Problem Credits: vgoofficial
Analysis: vgoofficial
First, what is the maximum possible value of $$$c_i-b_j$$$ for any $$$i,j$$$? Since $$$c_i$$$ is the maximum element of some subset of $$$a$$$ and $$$b_i$$$ is the minimum element of some subset of $$$a$$$, the maximum possible value of $$$c_i-b_j$$$ is $$$max(a)-min(a)$$$.
Also note that $$$c_1=b_1$$$ for any reordering of $$$a$$$. By reordering such that the largest element of $$$a$$$ appears first and the smallest element of $$$a$$$ appears second, the maximum possible value of the score is achieved. This results in a score of $$$(max(a)-min(a))\cdot(n-1)$$$.
for i in range(int(input())):
n = int(input())
mx = 0
mn= 1000000
lst = input().split()
for j in range(n):
x = int(lst[j])
mx = max(mx, x)
mn = min(mn, x)
print((mx-mn)*(n-1))
2030B - Minimise Oneness
Problem Credits: vgoofficial
Analysis: vgoofficial
Observation: $$$f(t)-g(t)$$$ is odd.
Proof: $$$f(t)+g(t)$$$ is the set of all non-empty subsets of $$$t$$$, which is $$$2^{|t|}-1$$$, which is odd. The sum and difference of two integers has the same parity, so $$$f(t)-g(t)$$$ is always odd.
By including exactly one $$$1$$$ in the string $$$s$$$, we can make $$$f(s)=2^{n-1}-1$$$ and $$$g(s)=2^{n-1}$$$, or $$$f(s)-g(s)=1$$$ by the multiplication principle. Clearly, this is the best we can do. So, we print out any string with exactly one $$$1$$$.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
cout << '1';
for(int i = 1; i < n; i++) cout << '0';
cout << endl;
}
}
2030C - A TRUE Battle
Problem Credits: vgoofficial
Analysis: vgoofficial
Let's understand what Alice wants to do. She wants to separate a statement that evaluates to true
between two or
's. This guarantees her victory since or
is evaluated after all and
's.
First, if the first or last boolean is true
, then Alice instantly wins by placing or
between the first and second, or second to last and last booleans.
Otherwise, if there are two true
's consecutively, Alice can also win. Alice may place or
before the first of the two on her first move. If Bob does not put his operator between the two true
's, then Alice will put an or
between the two true
's on her next move and win. Otherwise, Bob does place his operator between the two true
's. However, no matter what Bob placed, the two true
's will always evaluate to true
, so on her second move Alice can just place an or
on the other side of the two true
's to win.
We claim these are the only two cases where Alice wins. This is because otherwise, there does not contain two true
's consecutively. Now, whenever Alice places an or
adjacent to a true
, Bob will respond by placing and
after the true
, which will invalidate this clause to be false.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
string s;
cin >> s;
vector<int> v(n);
for(int i = 0; i < n; i++) {
if(s[i]=='1') v[i]=1;
}
bool win = false;
if(v[0]||v[n-1]) win=true;
for(int i = 1; i < n; i++) {
if(v[i]&&v[i-1]) win=true;
}
if(win) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
2030D - QED's Favorite Permutation
Problem Credits: vgoofficial, cry
Analysis: cry
Observation: Through a series of swaps, we can swap an element from position $$$i$$$ to position $$$j$$$ (WLOG, assume $$$i < j$$$) if there is no such $$$k$$$ such that $$$i \leq k < j$$$ such that $$$s_k = \texttt{L}$$$ and $$$s_{k+1} = \texttt{R}$$$.
Let's mark all indices $$$i$$$ such that $$$s_i = \texttt{L}$$$ and $$$s_{i+1} = \texttt{R}$$$ as bad. If $$$pos_i$$$ represents the position of $$$i$$$ in $$$p$$$, then we must make sure it is possible to swap from $$$\min(i, pos_i)$$$ to $$$\max(i, pos_i)$$$. As you can see, we can model these conditions as intervals. We must make sure there are no bad indices included in any intervals.
We need to gather indices $$$i$$$ such that $$$i$$$ is included in at least one interval. This can be done with difference array. Let $$$d_i$$$ denote the number of intervals that include $$$i$$$. If $$$d_i > 0$$$, then we need to make sure $$$i$$$ is not a bad index.
We can keep all bad indices in a set. Notice that when we update $$$i$$$, we can only potentially toggle indices $$$i$$$ and $$$i-1$$$ from good to bad (or vice versa). For example, if $$$s_i = \texttt{L}$$$, $$$s_i = \texttt{R}$$$, $$$d_i > 0$$$ and index $$$i$$$ is not in the bad set, then we will insert it. After each query, if the bad set is empty, then the answer is "YES".
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int n,q;
cin >> n >> q;
vector<int> perm(n);
for(int i = 0; i < n; i++) cin >> perm[i];
for(int i = 0; i < n; i++) perm[i]--;
vector<int> invperm(n);
for(int i = 0; i < n; i++) invperm[perm[i]]=i;
vector<int> diffArr(n);
for(int i = 0; i < n; i++) {
diffArr[min(i, invperm[i])]++;
diffArr[max(i, invperm[i])]--;
}
for(int i = 1; i < n; i++) diffArr[i]+=diffArr[i-1];
string s;
cin >> s;
set<int> problems;
for(int i = 0; i < n-1; i++) {
if(s[i]=='L'&&s[i+1]=='R'&&diffArr[i]!=0) {
problems.insert(i);
}
}
while(q--) {
int x;
cin >> x;
x--;
if(s[x]=='L') {
s[x]='R';
} else {
s[x]='L';
}
if(s[x-1]=='L'&&s[x]=='R'&&diffArr[x-1]!=0) {
problems.insert(x-1);
} else {
problems.erase(x-1);
}
if(s[x]=='L'&&s[x+1]=='R'&&diffArr[x]!=0) {
problems.insert(x);
} else {
problems.erase(x);
}
if(problems.size()) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
}
}
}
}
2030E - MEXimize the Score
Problem Credits: vgoofficial, cry, satyam343
Analysis: cry
Observation: The score of $$$b$$$ is equivalent to $$$f_0$$$ + $$$\min(f_0, f_1)$$$ + $$$\ldots$$$ + $$$\min(f_0, \ldots, f_{n-1})$$$ where $$$f_i$$$ stores the frequency of integer $$$i$$$ in $$$b$$$.
Intuition: We can greedily construct the $$$k$$$ arrays by repeating this step: Select the minimum $$$j$$$ such that $$$f_j = 0$$$ and $$$\min(f_0, \ldots f_{j-1}) > 0$$$, and construct the array $$$[0, 1, \ldots, j-1]$$$. This is optimal because every element we add will increase the MEX by $$$1$$$, which will increase the score by $$$1$$$. If we add $$$j$$$, the MEX will not increase. Also, when we add an element, we cannot increase the score by more than $$$1$$$. Adding less than $$$j$$$ elements cannot increase MEX for future arrays.
From this observation, we can see that only the frequency array of $$$a$$$ matters. From now on, let's denote the frequency of $$$i$$$ in $$$a$$$ as $$$f_i$$$. We can find the sum over all subsequences using dynamic programming.
Let's denote $$$dp[i][j]$$$ as the number of subsequences containing only the first $$$i$$$ integers and $$$min(f_0, \ldots, f_i) = j$$$. Initially, $$$dp[0][i] = \binom{f_0}{i}$$$. To transition, we need to consider two cases:
In the first case, let's assume $$$j < \min(f_0, \ldots, f_{i-1})$$$. The number of subsequences that can be created is $$$(\sum_{k=j+1}^n dp[i-1][k]) \cdot \binom{f_i}{j}$$$. That is, all the subsequences from previous length such that it is possible for $$$j$$$ to be the new minimum, multiplied by the number of subsequences where $$$f_i = j$$$.
In the second case, let's assume $$$j \geq \min(f_0, \ldots, f_{i-1})$$$. The number of subsequences that can be created is $$$(\sum_{k=j}^{f_i} \binom{f_i}{k}) \cdot dp[i-1][j]$$$. That is, all subsequences containing at least $$$j$$$ elements of $$$i$$$, multiplied by all previous subsequences with minimum already equal to $$$j$$$.
The total score is $$$dp[i][j] \cdot j \cdot 2^{f_{i+1} + \dots + f_{n-1}}$$$ over the length of the prefix $$$i$$$ and prefix minimum $$$j$$$.
We can speed up the calculations for both cases using suffix sums, however, this still yields an $$$O(n^2)$$$ algorithm. However, $$$j$$$ is bounded to the interval $$$[1, f_i]$$$ for each $$$i$$$. Since the sum of $$$f_i$$$ is $$$n$$$, the total number of secondary states is $$$n$$$. This becomes just a constant factor, so the total complexity is $$$O(n)$$$.
#include <bits/stdc++.h>
#define int long long
#define ll long long
#define pii pair<int,int>
#define piii pair<pii,pii>
#define fi first
#define se second
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
using namespace std;
const int MX = 2e5;
ll fact[MX+1];
ll ifact[MX+1];
ll MOD=998244353;
ll binPow(ll base, ll exp) {
ll ans = 1;
while(exp) {
if(exp%2) {
ans = (ans*base)%MOD;
}
base = (base*base)%MOD;
exp /= 2;
}
return ans;
}
int nCk(int N, int K) {
if(K>N||K<0) {
return 0;
}
return (fact[N]*((ifact[K]*ifact[N-K])%MOD))%MOD;
}
void ICombo() {
fact[0] = 1;
for(int i=1;i<=MX;i++) {
fact[i] = (fact[i-1]*i)%MOD;
}
ifact[MX] = binPow(fact[MX],MOD-2);
for(int i=MX-1;i>=0;i--) {
ifact[i] = (ifact[i+1]*(i+1))%MOD;
}
}
void solve() {
int n, ans=0; cin >> n;
vector<int> c(n);
for (int r:c) {
cin >> r; c[r]++;
}
vector<vector<int>> dp(n,vector<int>(1));
vector<int> ps, co;
for (int i = 1; i <= c[0]; i++) dp[0].push_back(nCk(c[0],i));
for (int i = 1; i < n; i++) {
ps.resize(1); co=ps;
for (int r:dp[i-1]) ps.push_back((ps.back()+r)%MOD);
int m=ps.size()-1;
dp[i].resize(min(m,c[i]+1));
for (int j = 0; j <= c[i]; j++) co.push_back((co.back()+nCk(c[i],j))%MOD);
for (int j = 1; j < dp[i].size(); j++) dp[i][j]=nCk(c[i],j)*(ps[m]-ps[j]+MOD)%MOD+(co.back()-co[j+1]+MOD)*dp[i-1][j]%MOD;
}
int j=0;
for (auto r:dp) {
n-=c[j++];
for (int i = 1; i < r.size(); i++) (ans+=i*r[i]%MOD*binPow(2,n))%=MOD;
}
cout << ans << "\n";
}
int32_t main() {
ios::sync_with_stdio(0); cin.tie(0);
ICombo();
int t = 1; cin >> t;
while (t--) solve();
}
2030F - Orangutan Approved Subarrays
Problem Credits: vgoofficial, satyam343
Analysis: vgoofficial
First, let's try to find whether a single array is orangutan-approved or not.
Claim: The array $$$b$$$ of size $$$n$$$ is not orangutan-approved if and only if there exists indices $$$1\leq w < x < y < z \leq n$$$ such that $$$b_w=b_y$$$, $$$b_x=b_z$$$, and $$$b_w\neq b_x$$$.
Proof: Let's prove this with strong induction. For $$$n=0$$$, the claim is true because the empty array is orangutan-approved. Now, let's suppose that the claim is true for all $$$m < n$$$.
Now, let $$$s$$$ be a sorted sequence such that $$$x$$$ is in $$$s$$$ if and only if $$$b_x=b_1$$$. Suppose $$$s$$$ is length $$$k$$$. We can split the array $$$b$$$ into disjoint subarrays $$$c_1, c_2, \ldots, c_k$$$ such that $$$c_i$$$ is the subarray $$$b[s_i+1\ldots s_{i+1}-1]$$$ for all $$$1 \leq i < k$$$ and $$$c_k=b[s_k+1\ldots n]$$$ That is, $$$c_i$$$ is the subarray that lies between each occurrence of $$$b_1$$$ in the array $$$b$$$.
First, we note that the set of unique elements of $$$c_i$$$ and $$$c_j$$$ cannot contain any elements in common for all $$$i\neq j$$$. This is because suppose that there exists $$$i$$$ and $$$j$$$ such that $$$i < j$$$ and the set of unique values in $$$c_i$$$ and $$$c_j$$$ both contain $$$y$$$. Then, in the original array $$$b$$$, there must exist a subsequence $$$b_1, y, b_1, y$$$. This makes our premise false.
By our inductive claim, each of the arrays $$$c_1, c_2, \ldots, c_k$$$ must be orangutan-approved. Since there are no overlapping elements, we may delete each of the arrays $$$c_1, c_2, \ldots, c_k$$$ separately. Finally, the array $$$b$$$ is left with $$$k$$$ copies of $$$b_1$$$, and we can use one operation to delete all remaining elements in the array $$$b$$$.
Now, how do we solve for all queries? First, precompute the array $$$last$$$, which is the array containing for each $$$i$$$ the largest index $$$j<i$$$ such that $$$a[j]=a[i]$$$. Let's then use two pointers to compute the last element $$$j<i$$$ such that $$$a[j\ldots i]$$$ is orangutan-approved but $$$a[j-1\ldots i]$$$ is not, and store this in an array called $$$left$$$. Let's also keep a maximum segment tree $$$next$$$ such that $$$next[i]$$$ is the first element $$$j>i$$$ such that $$$a_j=a_i$$$. As we sweep from $$$i-1$$$ to $$$i$$$, we do the following:
Set $$$L=left[i-1]$$$
Otherwise, while $$$\max(next[L...last[i]-1]>last[i]$$$ and $$$last[i]\neq-1$$$), increment $$$L$$$ by $$$1$$$.
Set $$$left[i]=L$$$
When the $$$left$$$ array is fully calculated, we can solve each query in $$$O(1)$$$.
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define nline "\n"
#define f first
#define s second
#define sz(x) x.size()
#define all(x) x.begin(),x.end()
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const ll INF_ADD=1e18;
const ll MOD=1e9+7;
const ll MAX=1048579;
class ST {
public:
vector<ll> segs;
ll size = 0;
ll ID = 0;
ST(ll sz) {
segs.assign(2 * sz, ID);
size = sz;
}
ll comb(ll a, ll b) {
return max(a, b);
}
void upd(ll idx, ll val) {
segs[idx += size] = val;
for(idx /= 2; idx; idx /= 2) segs[idx] = comb(segs[2 * idx], segs[2 * idx + 1]);
}
ll query(ll l, ll r) {
ll lans = ID, rans = ID;
for(l += size, r += size + 1; l < r; l /= 2, r /= 2) {
if(l & 1) lans = comb(lans, segs[l++]);
if(r & 1) rans = comb(segs[--r], rans);
}
return comb(lans, rans);
}
};
void solve(){
ll n,q,l=1; cin>>n>>q;
ST track(n+5);
vector<ll> a(n+5),last(n+5,0),lft(n+5);
for(ll i=1;i<=n;i++){
cin>>a[i];
ll till=last[a[i]];
while(track.query(l,till)>=till+1){
l++;
}
if(till){
track.upd(till,i);
}
lft[i]=l;
last[a[i]]=i;
}
while(q--) {
ll l,r; cin>>l>>r;
if(lft[r]<=l){
cout<<"YES\n";
}
else{
cout<<"NO\n";
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
ll test_cases=1;
cin>>test_cases;
while(test_cases--){
solve();
}
}
2030G1 - The Destruction of the Universe (Easy Version) and 2030G2 - The Destruction of the Universe (Hard Version)
Problem Credits: vgoofficial, satyam343
Analysis: satyam343
To find the score of a set of intervals $$$([l_1, r_1], [l_2, r_2], \ldots, [l_v, r_v])$$$, we follow these steps:
Initially, the score is set to $$$0$$$.
We perform the following process repeatedly:
- Let $$$x$$$ be the interval with the smallest $$$r_i$$$ among all active intervals.
- Let $$$y$$$ be the interval with the largest $$$l_i$$$ among all active intervals.
- If $$$r_x < l_y$$$, add $$$l_y - r_x$$$ to the score, mark intervals $$$x$$$ and $$$y$$$ as inactive, and continue the process.
- If $$$r_x \geq l_y$$$, stop the process.
At the end of this process, all active intervals will intersect at least one common point.
Now, we need to prove that the process indeed gives us the minimum possible score. We can prove this by induction.
Let $$$S$$$ be some set of intervals, and let $$$x$$$ and $$$y$$$ be the intervals defined above. Consider the set $$$S' = S \setminus {x, y}$$$ (i.e., $$$S'$$$ is the set $$$S$$$ excluding $$$x$$$ and $$$y$$$). We claim that:
This is true because, for $$$x$$$ and $$$y$$$ to intersect, we must perform at least $$$\text{distance}(x, y)$$$ operations. Our construction achieves the lower bound of $$$\text{score}(S') + \text{distance}(x, y)$$$. Thus,
During the process, we pair some intervals (possibly none). Specifically, in the $$$k$$$-th step, we pair the interval with the $$$k$$$-th smallest $$$r_i$$$ with the interval having the $$$k$$$-th largest $$$l_j$$$, and add the distance between them to the score.
In the problem G1, we can compute the contribution of each pair of intervals as follows:
Suppose we consider a pair $$$(i, j)$$$. Without loss of generality, assume that $$$r_i < l_j$$$.
The pair $$$(i, j)$$$ will be considered in some subset $$$S$$$ if there are exactly $$$x$$$ intervals $$$p$$$ such that $$$r_p < r_i$$$ and exactly $$$x$$$ intervals $$$p$$$ such that $$$l_p > l_j$$$, for some non-negative integer $$$x$$$.
Let there be $$$g$$$ intervals $$$p$$$ such that $$$r_p < r_i$$$ and $$$h$$$ intervals $$$p$$$ such that $$$l_p > l_j$$$.
For $$$(i, j)$$$ to be paired in some subset $$$S$$$, we must choose $$$x$$$ intervals from the $$$g$$$ intervals on the left and $$$x$$$ intervals from the $$$h$$$ intervals on the right, for some non-negative integer $$$x$$$. There are no restrictions on the remaining $$$n - 2 - g - h$$$ intervals.
Therefore, the contribution of $$$(i, j)$$$ is:
We can simplify this sum using the identity:
(This is a form of the Vandermonde Identity.)
Thus, the contribution of $$$(i, j)$$$ becomes:
This can be computed in $$$O(1)$$$ time.
Note that in the explanation above, we assumed that the interval endpoints are distinct for simplicity. If they are not, we can order the intervals based on their $$$l_i$$$ values to maintain consistency.
Let us find the contribution of $$$r[i]$$$, the right endpoint of $$$i$$$-th interval.
Let $$$x$$$ be the number of intervals $$$j$$$ such that $$$r[j] < r[i]$$$, and let $$$y$$$ be the number of intervals $$$j$$$ such that $$$l[j] > r[i]$$$.
To determine the contribution of $$$r[i]$$$ to the final answer, we consider selecting $$$p$$$ intervals from the $$$x$$$ intervals to the left and $$$q$$$ intervals from the $$$y$$$ intervals to the right, with the constraint that $$$p < q$$$. We require $$$p < q$$$ so that interval $$$i$$$ is paired with some other interval on the right (as discussed in the solution for G1). Therefore, the contribution of $$$r[i]$$$ can be expressed as:
Here, $$$\text{ways}(x, y)$$$ represents the number of valid selections where $$$p < q$$$.
Calculating $$$\text{ways}(x, y)$$$
To compute $$$\text{ways}(x, y)$$$, we can use the Vandermonde identity to simplify the expression:
This can be rewritten as:
Define the function $$$g(k)$$$ as:
By applying the Vandermonde identity, we get:
Thus, the total number of ways is:
We can simplify this summation using the property of binomial coefficients:
where the function $$$h(p, q)$$$ is defined as:
Efficient Computation of $$$h(p, q)$$$
Note that:
Suppose throughout the solution, we call the function $$$h(p, q)$$$ $$$d$$$ times for pairs $$$(p_1, q_1), (p_2, q_2), \ldots, (p_d, q_d)$$$, in that order. We can observe that:
Since $$$h(p_i, q_i)$$$ can be computed from $$$h(p_{i-1}, q_{i-1})$$$ in $$$|p_i - p_{i-1}| + |q_i - q_{i-1}|$$$ operations, the amortized time complexity for this part is $$$O(n)$$$.
Final Contribution
Combining the above results, the contribution of $$$r[i]$$$ to the answer is:
A similar calculation can be applied to the contribution of $$$l[i]$$$. By summing these contributions across all relevant intervals, we obtain the final answer.
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
#define ll long long
#define ld long double
#define nline "\n"
#define f first
#define s second
#define sz(x) (ll)x.size()
#define vl vector<ll>
const ll INF_MUL=1e13;
const ll INF_ADD=1e18;
#define all(x) x.begin(),x.end()
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const ll MOD=998244353;
const ll MAX=500500;
vector<ll> fact(MAX+2,1),inv_fact(MAX+2,1);
ll binpow(ll a,ll b,ll MOD){
ll ans=1;
a%=MOD;
while(b){
if(b&1)
ans=(ans*a)%MOD;
b/=2;
a=(a*a)%MOD;
}
return ans;
}
ll inverse(ll a,ll MOD){
return binpow(a,MOD-2,MOD);
}
void precompute(ll MOD){
for(ll i=2;i<MAX;i++){
fact[i]=(fact[i-1]*i)%MOD;
}
inv_fact[MAX-1]=inverse(fact[MAX-1],MOD);
for(ll i=MAX-2;i>=0;i--){
inv_fact[i]=(inv_fact[i+1]*(i+1))%MOD;
}
}
ll nCr(ll a,ll b,ll MOD){
if((a<0)||(a<b)||(b<0))
return 0;
ll denom=(inv_fact[b]*inv_fact[a-b])%MOD;
return (denom*fact[a])%MOD;
}
ll l[MAX],r[MAX],lft[MAX],rght[MAX],power[MAX];
void solve(){
ll n; cin>>n;
power[0]=1;
for(ll i=1;i<=n;i++){
cin>>l[i]>>r[i];
power[i]=(power[i-1]*2ll)%MOD;
}
for(ll i=1;i<=n;i++){
lft[i]=rght[i]=0;
for(ll j=1;j<=n;j++){
if(make_pair(r[i],i)>make_pair(r[j],j)){
lft[i]++;
}
if(make_pair(l[i],i)<make_pair(l[j],j)){
rght[i]++;
}
}
}
ll ans=0;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
if(r[i]<l[j]){
ll found=lft[i]+rght[j];
ll now=nCr(found,lft[i],MOD)*(l[j]-r[i]);
now%=MOD;
ll remaining=n-found-2;
ans=(ans+now*power[remaining])%MOD;
}
}
}
cout<<ans<<nline;
return;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
ll test_cases=1;
cin>>test_cases;
precompute(MOD);
while(test_cases--){
solve();
}
cout<<fixed<<setprecision(12);
cerr<<"Time:"<<1000*((double)clock())/(double)CLOCKS_PER_SEC<<"ms\n";
}
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
#define ll long long
#define ld long double
#define nline "\n"
#define f first
#define s second
#define sz(x) (ll)x.size()
#define vl vector<ll>
const ll INF_MUL=1e13;
const ll INF_ADD=1e18;
#define all(x) x.begin(),x.end()
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const ll MOD=998244353;
const ll MAX=5000500;
vector<ll> fact(MAX+2,1),inv_fact(MAX+2,1);
ll binpow(ll a,ll b,ll MOD){
ll ans=1;
a%=MOD;
while(b){
if(b&1)
ans=(ans*a)%MOD;
b/=2;
a=(a*a)%MOD;
}
return ans;
}
ll inverse(ll a,ll MOD){
return binpow(a,MOD-2,MOD);
}
void precompute(ll MOD){
for(ll i=2;i<MAX;i++){
fact[i]=(fact[i-1]*i)%MOD;
}
inv_fact[MAX-1]=inverse(fact[MAX-1],MOD);
for(ll i=MAX-2;i>=0;i--){
inv_fact[i]=(inv_fact[i+1]*(i+1))%MOD;
}
}
ll nCr(ll a,ll b,ll MOD){
if((a<0)||(a<b)||(b<0))
return 0;
ll denom=(inv_fact[b]*inv_fact[a-b])%MOD;
return (denom*fact[a])%MOD;
}
ll l[MAX],r[MAX],power[MAX];
ll ans=0,on_left=0,on_right,len;
ll x=0,y=0,ways=0,inv2;
ll getv(){
while(x>=len+1){
ways=((ways+nCr(x-1,y,MOD))*inv2)%MOD;
x--;
}
while(x<=len-1){
ways=(2ll*ways-nCr(x,y,MOD)+MOD)%MOD;
x++;
}
while(y<=on_left-1){
ways=(ways+nCr(x,y+1,MOD))%MOD;
y++;
}
return ways;
}
void solve(){
ll n; cin>>n;
power[0]=1;
vector<array<ll,2>> track;
multiset<ll> consider;
for(ll i=1;i<=n;i++){
cin>>l[i]>>r[i];
track.push_back({r[i],l[i]});
consider.insert(l[i]);
power[i]=(power[i-1]*2ll)%MOD;
}
ans=on_left=0;
on_right=len=n;
x=y=0; ways=1;
sort(all(track));
for(auto it:track){
while(!consider.empty()){
if(*consider.begin() <= it[0]){
consider.erase(consider.begin());
on_right--,len--;
}
else{
break;
}
}
ll now=power[len]-getv();
now=(now*power[n-1-len])%MOD;
now=(now*it[0])%MOD;
ans=(ans+MOD-now)%MOD;
on_left++,len++;
}
track.clear(); consider.clear();
for(ll i=1;i<=n;i++){
track.push_back({l[i],r[i]});
consider.insert(r[i]);
}
sort(all(track));
reverse(all(track));
on_left=0;
on_right=len=n;
x=y=0; ways=1;
for(auto it:track){
while(!consider.empty()){
if(*(--consider.end()) >= it[0]){
consider.erase(--consider.end());
on_right--,len--;
}
else{
break;
}
}
ll now=power[len]-getv();
now=(now*power[n-1-len])%MOD;
now=(now*it[0])%MOD;
ans=(ans+now)%MOD;
on_left++,len++;
}
ans=(ans+MOD)%MOD;
cout<<ans<<nline;
return;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
ll test_cases=1;
cin>>test_cases;
precompute(MOD);
inv2=inverse(2,MOD);
while(test_cases--){
solve();
}
cout<<fixed<<setprecision(12);
cerr<<"Time:"<<1000*((double)clock())/(double)CLOCKS_PER_SEC<<"ms\n";
}
Thanks to the authors for the interesting tasks :D
Sad for F... I did every observations required to solve problem but i could not combine it :(
Fast solution Updated! Thanks
StringForces
YESNO-Forces
Can you please not frozen the standings?
I want to read others' submission for problem G NOW as the editorial is not published yet.
System Testing may have begun, it gets completed in ~1 hour or lesser depending on the pretests accepted submissions.
Though submissions will be available now, you can use the status tab as soon as a contest finishes to view and filter other submissions.
The difficulty of problem F may be a little bit low.
D and F are both nice problems!
D felt like I needed a data structure I don't know of. Any ideas?
I don't get the editorial too much. Please look at my submission, it is more straightforward. All you need to so is make an array with the max from the front and min from the back. For the array, 1 4 2 5 3, mx is [1,4,4,5,5] and mn is [1,2,2,3,3]. For any index such that s[i] == 'L' && s[i+1] == 'R' it is enough the check if max[i] <= mn[i+1], if so, the index is not a problem. Store the number of problems. It is not necessary to store the indices. When you change an index to L from R or vice Versa, check the indexes around it to see if the bad count would be affected. If bad==0, SAY yes else say no. Submission: https://codeforces.me/contest/2030/submission/286799491
I don't see why you use both a max prefix and a min suffix.
Build first a max prefix array $$$pref$$$. As you said, you can iterate over $$$i$$$ and check if $$$s[i] == 'L' && s[i+1] == 'R'$$$. It is a potential block, since it will prevent any element with index below or equal to $$$i$$$ to go to a position with index over $$$i$$$ (and reciproquely).
But it is only a problem if this prevents us to sort the array. This isn't a problem if all elements below index $$$i$$$ can be sorted independantely, i.e. there are values from $$$1$$$ to $$$i$$$. In this case, $$$pref[i] == i$$$. If $$$pref[i] > i$$$, then the block is active, and we count one conflict.
Count the number of initial conflicts, and for each query, you can check locally if this resolves a conflict or create one.
Ok i was confused at first but i think your solution relies on the fact that it is a permutation. To be honest, I completely missed the fact that it was a permutation hence my general solution, still I think my solution is easier to think about and also more general. I assume in your solution if pref[i]<i you do nothing since the conflict would be counted before? But the fact that I even have to think about that makes my solution a little better I think.
Yeah you're right, this works since it is a permutation. In this case, $$$pref[i]$$$ is always greater or equal to $$$i$$$
oh true lmao
This is a nice observation that makes the code more simple. If
pref[i] > i
, it means there's a number missing from 1 to $$$i$$$. Then you can use the prefix array to do all necessary checks while updating the input string. I wish I'd have thought of it during the contest.Elegant solution.
I cannot see your solution. I am seeing N/A in the code. Any reason for this.
how did you come up with this idea? did you solve such a question before if so do let me know.
you can see that for any substring of S, that doesnt contain the substring LR in itself, that substring is sortable. thus it is sufficient to check whether the substrings of LR partition the string into parts that, when sorted make the entire array sorted. you can do that by constructing intervals where l=min(pos[i],i) and r=max(pos[i],i). what this means essentially is just an interval that starts where the number is and where its supposed to be(or vice versa). then another observation is that if 2 intervals intersect, then you can merge them and they can be considered one interval. next for each query you can just check whether this changes the amount of LRs in the entire string and if an LR dissapears then check if it previously "ruined" the array, or if an LR appears, check if the new LR "ruins" the array. sorry if this is unclear, but ask any questions, id be glad to explain further.
i did something similar , to check if segment is sortable or no
compare its sum [ l ,r ] it should be equal to [ l, r ] when the array is sorted ( we created a sorted permutation from( 1 , n )) to compare the segments
I tried doing it using segment tree and set, here is my solution, 287045819
Thanks for the contest and fast editorials ༼ つ ◕_◕ ༽つ
My solution to D is in $$$O(n + q)$$$, using prefix sums. https://codeforces.me/contest/2030/submission/286798401
u don't even need prefix-sum. You can use prefix max and suffix min. That should be sufficient I guess.
How would that work?
check my comment above
if there is someone, who is smaller than current index on its right side, means, you can't have 'LR' ( boundary at index 'i' ) .
Same goes for left side.
Oh I actually did something different. I did prefix sums, but instead of maintaining a set, I maintained the sum, and checked if the sum was $$$0$$$. Your solution is good too.
Even prefix max is enough, my solution
f similar to https://open.kattis.com/problems/wiknow although still couldn't solve it :(
Can we just appreciate the Round Timeline :)
It was really insightful as to how problems are actually made and well the coordination skills of satyam343
the thing that caught my eye was the D'''''''' lmao
Started happily with A and B. C crashed and burnt for me. couldn't figure out :(.
same bro
can anyone help me find mistake in my code for D.My logic was same.. here is my submission 286813972
Another solution for D is to precalculate all intervals in the array that are permutations of their indices and process the queries with a segment tree. You can store the array intervals' ends in a set and, for each bad index LR in the string, you can consider it as two intervals: one ends at L and the other starts at R. For the permutation to be sortable, every string interval's end must also be an end in the set of indices we calculated for an array.
So the segment tree on the LR string can store nodes that contains the leftmost character on the range, the rightmost character on the range, and whether or not all the endings in the range are also in the set of array indices. If they are, then we are able to sort that range. The tree can be updated in $$$O(\log{n})$$$, and the answer is the root of the segment tree.
This is probably the most leetcode submission idea. I had something similar. Takes forever to implement though.
could u explain this part more ?
and whether or not all the endings in the range are also in the set of array indices
u dont need segment tree bcz ur check function ```if (left.right == 'L' && right.left == 'R') { if (ends.count(mid)) { seg_tree[node — 1] = {left.left, right.right, true}; } else { seg_tree[node — 1] = {left.left, right.right, false}; } } else { seg_tree[node — 1] = {left.left, right.right, true}; }
``` u are only checking when u are the next node from the leaf of segment tree ,
u can check it manually on array ( 2 adjacent indicies who = "LR" )
you could also try xor hashing. congrats on cm btw.
thanks!
When you have seen the problem statement somewhere else...
(Of course, it's okay since the problem requirement is totally different)
Well well well, the author looks familiar as well... :)
our supreme problemsetter went ahead and took the chance to steal the statement from HIMSELF
Alternate solution to problem C: Notice that the substring "010" is bad, we just need to check if there is a '1' that is not inside "010" then the answer is YES, otherwise NO
Can u please elaborate I had similar approach so I have check if 010 in string or 010 in start or 101 in end but got wa
Basically, the idea for substring "010" is there are 2 options to choose from: "01" or "10".
We know that the "and" operations will be evaluated first, so even if Alice moves before Bob, no matter which she chooses to do the "or" operation on, Bob can "counter-attack" that move by choosing the other one. Which means the substring "010" will always become "000".
For any other cases where there is a '1', because Alice moves first, Alice can pair that '1' with whatever other digit that is next to it to do the "or" operation and get the result of '1'. Bob cannot "counter-attack" it, because he can not make that '1' become '0' before Alice if the substring is not "010", so Alice will have at least one '1' at the end. She will win.
It's just my intuition and some deducing while solving the problem, hope it helps!
let f(t) be the number of non-empty subsequences† of t that contain only 0
should be 0's
Nice contest! I just fumbled in D problem.
thanks for fast editorial
Great contest, and thank you for the fast editorial ! I was so close to finish D ... Next time I will
I wish I could have cracked B this time thought it was a nice experience as it was my first contest solved A and almost solved B and C will improve!
I think ignoring the fact that D is a permutation leads to a easier solution. Is this bad writing(still a great problem!) or was this intentional by the writers, just curious.
I can't get the proof of the given observation for problem E in the tutorial. Can anyone please explain it?
Let b = {0, 0, 1, 1}
f0 = 2, f1 = 2. Depending on the observation the score should be 4. But I can't get more than 3, doesn't matter how I perform the partition.
It is possible that I compiled the problem wrong. Hoping your help.
Thanks in advance.
Partition into multisets {0, 1} and {0, 1}, score is 2 + 2 = 4.
I just got it as soon as I posted the comment. My bad. It also fined me half of an hour during contest.
Thanks for your reply.
Wait. I think I get it. I am petitioning the array into subsegments during the whole contest. But It can be partitioned into subsequences.
I also was thinking the same, partition word hints that we need to divide the array into subsegments. Not happy with the statement of Problem E
https://codeforces.me/contest/2030/submission/286828473
I thought a little different for problem D but idk where it's going wrong. The basic intuition is the string should be of type R*L* (RRR...LLL). So, I stored the indices of L and R in two separate sets. If highest(SetR)<lowest(SetL) is true, answer to that query will be True. And if the array starts in correct order (1,2,3..) I neglect those indices, same for ending (..n-2,n-1,n). I'm unable to understand why this approach isn't working?
Got the error, I'm dumb
wats wrong with this approach
cool contest, maybe C was a bit too easy though?
How I solved A, B, C during the contest and D shortly after?
I would like any constructive feedback.
2030A - A Gift From Orangutan
I just had the key idea in my head. Is this what happens with red coders for all problems?
Clearly, max c_i — b_i is when c_i is max number in array and b_i in min number in array.
By placing a_max at index 0, we have c_i = a_max for all i
and by placing a_min at index 1, we have b_0 = a_max, and b_i = a_min for all i > 0
so we are sure now that every term from 1 to n-1 is max.
but first term = 0, can we do better? it turns out that first term will always equal 0 since c_0 = b_0 always..
So this is optimal, what is the required sum in this case? easy
first term = 0
rest of terms = a_max — a_min so we have (n-1) * (a_max — a_min)
2030B - Minimise Oneness
After playing around with some examples, I suspected that the optimal string is full all zeros except a single one..
I had a choice now, just to assume it is write or try to prove it
I decided to prove it
Let's assume
n -> string len
if all zeros except one one, then there are n-1 zeros
how many subsequences having only zeros -> 2^(n-1)
but there are one empty subsequence counted here, let's discard it so we have
f(t) = 2^(n-1) — 1
Key idea: for each of these subsequences there are a corresponding subsequence having the same zeros PLUS the only one we have..
Thus g(t) >= f(t)
but g(t) also include subsequences containing only ones
And if there is a single one, then such subsequences count = 1
Thus, g(t) = f(t) + 1
this means |f(t) — g(t)| = |f(t) — f(t) — 1| = 1
Yaaa, we find a way to make the required value = 1
since this is the absolute value of a number >= 0
the only question now can we make that value = 0 ?
Again, I had the choice of just assuming we can't, or waste more time trying to prove it during the contest..
I made the wrong decision to prove it. And here is my proof:
There are two cases:
1) no ones in the string, clearly g(t) = 0 but f(t) > 0 so the required value > 0
2) there are 1<=x<=n ones in the string , let's consider the this case
Let n0 = number of subsequences containing only zeros
Let n1 = number of subsequences containing only ones
It's not difficult to see that n0*n1 = number of subsequences having at least a one and some positive number of zeros
Clearly, f(t) = n0 and g(t) = n1 + n0 * n1 = (1 + n1) * n0
Thus, g(t) > f(t) so the required value in this case cannot be equal to 0
so we proved that in all cases, the required value >= 1
and we find a way to make it equal 1 which is the min possible
2030C - A TRUE Battle
After understanding the problem
I had the idea that Alice should always play 'or' and Bob should always play 'and'
Now, it wasn't difficult to notice that Alice needs to secure the life of a single 1 while Bob will try to kill all ones
A 'one' life is secured if it is guarded by 'or' from both sides, like this
(exp) or 1 or (exp)
It was not hard to make a number of observations now
a '1' at the beginning or end can be secured by one move only..
since Alice make the first move, if such a '1' exist then it will strive to secure it and secure the victory
Also, I just had another idea in my head that if there are two consecutive ones(not at boundaries), then Alice can secure one of them by force by immediately placing an 'or' in between
The situation reminded my of a similar situation in x-o game where the opponent is doomed because he needs to guard two places at the same time with just one move, also reminded me with double attack tactic in chess
(expr) 1 'or' 1
Alice is now threatening to place 'or' to the left if the first one and to the right of the second 1
I couldn't see a way bob can save this situation .. so the only remaining situation is
01010101010
Can Bob always hold his ground in this case?
Again I just had an intuitive idea that whenever Alice threatens to secure a '1' Bob will timely kill it by placing an 'and'
This was enough for me to conclude this problem
Alice wins if and only if string begins with 1, or ends with 1 or have two consecutive ones
2030D - QED's Favorite Permutation
After wandering aimlessly, I made an important observation
if s[i] = 'L' and s[i+1] = 'R' then the permutation si splitted into two isolated parts
meaning we cannot move any number at index <= i to an index > i or vice versa
Let's say there is a divide at index i, if this is the case
Now, if there is some number that must be moved from an index <= i to an index > i or vice versa, meaning
it must cross the divide then we call this a bad divide
Clearly, if the permutation is sortable then there are no bad divides
Here I made a very bold move and just assumed the converse it correct( I would be grateful if someone provided some casual compelling proof)
if there are no bad divides then the permutation is sortable
Thus, sortable if and only if no bad divides exists
So, we have a solution if we can maintain a set of bad divides and update it efficiently after each query, then
if that set is empty , the permutation is sortable and we output yes, otherwise no
So, I had two tasks now
1) calc the set of bad divides initially
2) update the set after each query (easy! since a query at index i may affect divides at i-1, i, i+1 only)
Let's focus on how to find the bad divides in the initial state
for each i, if p[i] != i, then number p[i] must move from index i to index p[i]
so any divide that would separate these two indexes will be considered bad..
let lo = min(i, p[i]) , hi = max(i, p[i])
Thus any divide at lo, lo+1, lo+2, ..., hi-1 is considered bad
To solve this problem, I defined array is_bad[i] = 0 if a divide at i not bad and positive integer otherwise
and then I used some trick I don't recall where I learn it by marking the first of the segment and end of segment
so is_bad[lo] += 1, and is_bad[hi] -= 1
then iterate through is_bad array accumulating is_bad[i] += is_bad[i-1]
Can someone help me recall what is trick related to? and any better solution for this subproblem?
Now, it's easy to construct the set of bad divides since it's easy to detect a divide
s[i] = 'L' and s[i+1] = 'R'
and it's easy to check if that divide is bad by checking is_bad[i]
I had all the ideas to solve the problem before the end of contest and I needed to code it under 15 minutes ..
Some things helped me while solving this interesting problem:
1. using 1-indexed ordering consistently, so instead of string s, I used vector s(n+1)
2. I wrote one portion of code then test it
so after writing the logic that computed is_bad array, I tested the code
same thing after writing bad divides set logic
Now, I did that by just printing things with cout,
Are there better ways without using a traditional debugger ?
Thanks
In C, not able to understand how alice wins in if there is 1 in end but odd number of strings. eg. 001: 0 or 0 and 1 -> 0
They can place the Boolean operator anywhere if the place is not captured already, like Alice will first place the OR operator between 0 and 1, I did the same mistake like you thinking that they will place it sequentially
Thanks @ritamiitism. This should have been highlighted in problem statement. :(
First 3 questions felt like speedForces but D was good, i could not do it. ps: thanks for the fast editorial!!
JUST SHARING MY THOUGHTS ON E
I felt E was quite hard enough. Instead of finding sum of all subsequences Mex, even if they had asked just number of different subsequences, such that their Mex is some given number(x)... that would have been good fit (IMO)
May be this could have been 2 part question,
1) first part: you have to compute number of ways,
2) second part: you have to compute the sum
cc : cry
Just reached master, thank you authors for these lovely problems.
orz
Could somebody please tell me why is my code for D incorrect at 4th test case? What am I missing?
.
I don't know if it's because of my rank but I think you need some work on the statements like problem C for example
I think C was pretty clear, but that clarification for B was important. I personally believe it should've been included in the statement
I was think that you must move from left to right I didn't get that it isn't work like that but the problem was very easy after that
Yeah true actually, that part is not clear from the statement. It's ambiguous
Love the round timeline! It's really fascinating to learn how contests are prepared, and how much time and efforts it takes. Thank you :)
My solution to D, using ordered sets in C++. I really liked the way this problem looked like a standard div3E/F exercise on data structures!
P. S. Back to blue with this contest! ^~^
Problem E
What does this mean? Can I partition
[2,0,1,0,3]
into[2,1,0,3]
and[0]
?Yes. It just means each element must be in exactly one multiset.
OK thanks
Hope everything will be better
In the problem B, I thought Alice and Bob can place the boolean operator from starting of the string sequentially. But now I realised after seeing the solution that they could place it anywhere. That's why it was giving wrong answer on test 2. The problem should have been mentioned it correctly, even the testcases and explanation was like sequential...
Another proof for problem B:
We can express $$$g(t)$$$ as the total number of subsequences, excluding those containing only zeros:
where
z
is the number of zeros. So the absolute difference becomes:As we aim for the smallest difference, let's assume it's 0:
as we can see, z can’t be an integer in this case.
Let's check for 1:
Thus, constructing a string with
n - 1
zeros is the best option.Problem D can be done using xor hashing as well in O(n).
286885996
can you explain your approach ?
As mentioned in the editorial, we can swap an element at position i to position j iff there is no LR b/w the positions. So we can divide the array into subarrays where the ith subarray ends at L and i + 1 th subarray starts at R.
So when can we make the permutation non decreasing? If the set of indexes and the set of elements of each subarray are same. To check if two subarrays are equal we can use xor hashing.
Implementation wise you can calculate a prefix array where prefix[i + 1] = pref[i] ^ hash[i] ^ hash[p[i]]. So when two subarrays are equal their prefix xor will be 0. So we can just maintain the good indexes where prefix xor is 0. So now we just need to check if the index where each subarray ends should be a good index i.e it's prefix xor should be zero.
Let me know if any part is unclear.
Ok I get it now , nice idea !
In case someone needs it, there's a nice tutorial about xor hashing.
Those who see my profile picture are handsome mans,haha
Are you serious?
Do you understand Belia?:(
Thanks authors for the contest.
Can someone explain why doing 2(fi+1+⋯+fn−1) to find the dp score in problem E does not overcount? Like we would count all subsequences longer which we will just consider later? Also wouldn't each dp overcount as well? Like every dp[2][2] is also a dp[1][2] so we would overcount by a lot?
in dp[i][j] you are guaranteed to increase the score by j using the occurences of ith element.
Each occurence of element i increases the score by 1
you are multiplying 2^(suffix sum) because you are calculating the contribution of every i's in every subsequence.
example case 1 : 0 1 2 case 2 : 0 1 2 4 40 400 case 3 : 0 1 2 3 4 5 6 7
they might have different mex's we dont care , what we do care about is the individual contribution.
if any one feels like this is wrong feel free to rectify me :)
F can be solved using XOR hashing hand Fenwick tree: submission link
Upd: Using this trick, I got the fastest solution to problem F: link
Can you explain your solution a little? I don't get it)
I didn't cheat the code style was popular to me and my friend he is my teammate so we use the same style by default, and we got it from our monitor
Problem D
1 3 5 2 4
L L R L L
if i swap 5,2 ,then 5,4 ,then 3,2 , i can sort it ,but answer is NO
why?
You can't swap 3 and 2
In problem E, in the 2nd case where $$$j \geq min(f_0, ..., f_{i-1})$$$, how can $$$j$$$ be greater than $$$min(f_0, ..., f_{i-1})$$$ when $$$j$$$ in $$$dp[i][j]$$$ itself is defined as $$$j=min(f_0, ..., f_i)$$$?
Moving from $$$i-1$$$ to $$$i$$$, prefix min either remains the same or decreases, right? But how can it increase?
cc: cry
Alternate solution for problem E:
We're going to calculate, for each value $$$i$$$ from $$$0$$$ to $$$n-1$$$, its contribution to the sum.
Let $$$f_i$$$ be the number of occurrences of value $$$i$$$. Following from the same observation as the editorial, value $$$i$$$ contributes $$$min(f_0, f_1, f_2 ... f_i)$$$ to the sum if the array is fixed. For short, let the result of that computation in the original array be $$$M_i$$$ and, in some subset, $$$m_i$$$. We want to compute for each value $$$i$$$ the sum of $$$m_i$$$ for every subset of $$$a$$$.
For the contribution of value $$$i$$$, the result of $$$m_i$$$ in each subset is not affected by the values greater than $$$i$$$ we choose. Let $$$S_i = \sum_{j=i+1}^{n-1}f_j$$$, that is, the sum of occurrences of values greater than $$$i$$$. We can compute the sum of $$$m_i$$$ for subsets less than $$$i$$$ and multiply that by $$$2^{S_i}$$$.
To compute the sum of $$$m_i$$$ over all subsets considering values less than $$$i$$$, we're going to calculate, for each possible value $$$x$$$ up to $$$M_i$$$, how many subsets exist such that $$$m_i = x$$$. Let $$$F(j,x) = \sum_{k=x}^{f_j}{{f_j}\choose{k}}$$$, that is, the amount of ways to choose at least $$$x$$$ elements from the amount of occurrences of $$$j$$$. The amount of subsets of values less than $$$i$$$ where $$$m_i = x$$$ is given by $$$G(i,x) = (\prod_{j=0}^iF(j,x)) - (\prod_{j=0}^iF(j,x+1))$$$, that is, the amount of subsets where the amount of occurrences of every value up to $$$i$$$ is at least $$$x$$$ minus the amount of subsets where the amount of occurrences of every value up to $$$i$$$ is at least $$$x+1$$$. From that, we know for each $$$x$$$ its contribution to the sum.
The answer to the problem can therefore be obtained by the following sum:
$$$\large{\sum_{i=0}^{n-1}2^{S_i}\cdot\sum_{x=1}^{M_i}{x \cdot G(i,x)}}$$$
These two outer sums amount to $$$\mathcal{O}(\sum_{i=0}^{n-1}f_i) = \mathcal{O}(n)$$$. However, the computation of $$$G(i,x)$$$ seems to make the overall complexity $$$\mathcal{O}(n^3)$$$ because of the computation of $$$F$$$ and $$$G$$$.
To compute $$$G$$$, we can note that, for each value of $$$x$$$, the value of $$$G(i,x)$$$ is given the product of all $$$j$$$ up to $$$i$$$ of $$$F(j,x)$$$ minus the same for $$$x+1$$$. Both terms are a product of $$$F$$$ for all $$$j$$$ up to $$$i$$$, so we can just store the cumulative product of each of the two of them for each value of $$$x$$$. Now, as we process values in ascending order, to get the result of $$$G(i,x)$$$, we only need to include the values of $$$F(i,x)$$$ and $$$F(i,x+1)$$$ in the cumulative products of $$$x$$$ we have already calculated.
Now, to compute $$$F$$$, we can note that we want to calculate a range sum in a row of binomial coefficients. We can precompute, for each value of $$$f_i$$$, the prefix sums of $$${f_i}\choose{k}$$$ for each $$$k$$$ up to $$$f_i$$$. The complexity for this is $$$\mathcal{O}(\sum_{i=0}^{n-1}f_i) = \mathcal{O}(n)$$$ and we can now query range sums (and compute $$$F$$$) in $$$\mathcal{O}(1)$$$.
From all of this, we can calculate the answer to the problem in $$$\mathcal{O}(n)$$$ total.
Code: 288412616