We'd like to thank you all for participating in the contest, and hope you enjoyed it. Any feedback would be appreciated!
2183A — Binary Array Game
Idea & Preparation: wangmarui
2183B — Yet Another MEX Problem
Idea & Preparation: wangmarui
2183C — War Strategy
Idea & Preparation: Network_Error
2183D1 — Tree Coloring (Easy Version)
Idea & Preparation: jiazhichen844
2183D2 — Tree Coloring (Hard Version)
Idea & Preparation: jiazhichen844
2183E — LCM is Legendary Counting Master
Idea & Preparation: Gold14526
2183F — Jumping Man
Idea & Preparation: Neil_Qian
2183G — Snake Instructions
Idea & Preparation: xvchongyv & wangmarui
2183H — Minimise Cost
Idea & Preparation: Hoks_ Special Thanks: Sorasaki_Hina
2183I1 — Pairs Flipping (Easy Version)
Idea & Preparation: Network_Error Special Thanks: N_z__
What if $$$s=1111\ldots$$$?
Try dividing the sequence into two equal halves, eliminating both halves by assigning odd and even lengths respectively.
Try processing recursively to reduce $$$n$$$ to a smaller scale.
Try further optimizing one of the two halves.
If $$$n$$$ is even, we only consider $$$s_1s_2\ldots s_{n-1}$$$. Now assume that $$$n$$$ is odd. Let $$$m=\frac{n-1}2$$$.
Consider dividing the $$$n$$$ numbers into the first $$$m$$$ and the last $$$m+1$$$ parts. The first $$$m$$$ are eliminated using odd lengths in $$$[1,m-1]$$$, and the last $$$m+1$$$ are eliminated using even lengths in $$$[1,m]$$$. (Assume that $$$m$$$ is even; it is similar when $$$m$$$ is odd.)
Let $$$solvePartially(l,r,p)$$$ denote the process of considering that there are 1s only in the interval $$$[l,r]$$$ and at some position $$$p$$$ outside $$$[l,r]$$$, and only using lengths in $$$[1,r-l]$$$ to eliminate. If $$$s_l=s_r=0$$$ or $$$s_l=s_r=1$$$, we operate on $$$l,r$$$ and recurse to $$$solvePartially(l+1,r-1,p)$$$; otherwise, assume that $$$s_l=1,s_r=0$$$ and $$$r \lt p$$$. If $$$p-(r-l)\in [l+1,r-1]$$$, we operate on $$$p-(r-l),p$$$ and then recurse to $$$solvePartially(l+1,r-1,l)$$$. Otherwise, the $$$1$$$ at $$$p$$$ is difficult to eliminate. Note that this situation occurs at most $$$\left\lfloor\log_3\frac{n}2\right\rfloor$$$ times, so we have obtained a solution with $$$c\le 2\left\lfloor\log_3\frac{n}2\right\rfloor+2$$$, roughly $$$24$$$ in the constraints of the problem, which is not acceptable.
Proof that the above situation occurs at most $$$\left\lfloor\log_3\frac{n}2\right\rfloor$$$ times:
- Note that the occurrence of an impossible elimination necessarily comes with $$$p-(r-l)\ge r$$$. Let $$$q+p=l+r$$$; then we must have $$$3(r-l)\le p-q$$$. Since $$$1\le r-l\le \frac{n}2$$$, it can happen at most $$$\left\lfloor\log_3\frac{n}2\right\rfloor$$$ times. In other words, each time an elimination is impossible, the interval length must reduce to $$$1/3$$$ of its original length.
In the above approach, the left and right sides are almost independent. Since operations on the left side are allowed to extend to the right side, we try to eliminate the left side completely. Let $$$solveCompletely(l,r,p)$$$ denote that the interval $$$[l,r]$$$ except for some position $$$p$$$ on the left side has been completely eliminated, and that we still need to eliminate position $$$p$$$ together with parts outside $$$[l,r]$$$. If $$$s_l=s_r=1$$$ or $$$s_l=s_r=0$$$, we eliminate $$$l,r$$$ and recurse to $$$solveCompletely(l-1,r+1,p)$$$; otherwise, assume that $$$s_l=1,s_r=0$$$, we eliminate $$$p,p+r-l$$$ and then recurse to $$$solveCompletely(l-1,r+1,l)$$$. In this way, for the left half, we can reduce it to a single remaining position $$$p$$$. Finally, we have optimised to $$$c\le \left\lfloor\log_3 \frac n2\right\rfloor+2$$$, which is below $$$14$$$ under the constraints of this problem. The code is easy to implement.
#include <bits/stdc++.h>
using namespace std;
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
string a;
cin >> a;
vector<int> ops(n/2+5);
auto operate = [&](int i)->void{
if(ops[i]==0) return;
else {
a[ops[i]-1]^=1;
a[ops[i]-1+i]^=1;
}
};
auto solveCompletely = [&](auto self, int l, int r, int x)->void{
if(l>r) return;
if(a[l]==a[r]) {
if(a[l]=='1') ops[r-l]=l+1, operate(r-l);
self(self, l+1, r-1, x);
return;
}
if(x!=-1 && x<l) {
if(x+r-l>=l) {
ops[r-l]=x+1, operate(r-l);
}
} else if(x!=-1 && x>r) {
if(x-r+l<=r) {
ops[r-l]=x-r+l+1, operate(r-l);
}
}
if(a[l]=='1') {
self(self, l+1, r-1, l);
} else {
self(self, l+1, r-1, r);
}
};
auto solvePartially = [&](auto self, int l, int r)->int{
if(l>r) return -1;
if(l==r) if(a[l]=='1') return l; else return -1;
int x = self(self, l+1, r-1);
if(a[l]==a[r]) {
if(a[l]=='1') ops[r-l]=l+1, operate(r-l);
return x;
} else {
if(x!=-1) {
ops[r-l]=x+1, operate(r-l);
}
if(a[l]=='1') return l;
else return r;
}
};
solvePartially(solvePartially, 0, (n-1)/2-1);
if(n%2) solveCompletely(solveCompletely, (n-1)/2, n-1, -1);
else solveCompletely(solveCompletely, (n-1)/2, n-2, -1);
for(int i=1; i<=n/2; i++) cout << ops[i] << " ";
cout << endl;
}
return 0;
}
2183I2 — Pairs Flipping (Hard Version)
Idea & Preparation: Network_Error
In the I1 approach, we can observe that the main cost arises from isolated $$$1$$$'s outside the interval that occasionally cannot be eliminated. We consider optimizing this situation.
The following diagram illustrates a scenario where such an elimination fails:
1111111111111|1??????0|1111111111110
p l r q
Here, $$$p$$$ is the previous $$$1$$$ we could not eliminate (without loss of generality, assume $$$p \lt l$$$), the current interval being processed is $$$[l,r]$$$, and $$$l-p \ge r-l$$$ (making it impossible to eliminate directly using the previous method). $$$q$$$ is the symmetric point of $$$p$$$.
At this point, the operation lengths we can use are $$$q-p-2, q-p-4, q-p-6, \ldots, r-l$$$. Note that $$$q-p$$$ is excluded because we have already used it earlier.
Let the lengths of the three segments be $$$A$$$, $$$B$$$, and $$$C$$$, where $$$A=C$$$. This scenario is denoted as $$$F(A,B,C)$$$.
Next, we will study in detail how to eliminate for $$$F(A,B,C)$$$.
If $$$A \lt B-1$$$, we have essentially solved it in I1.
For example, in a simple case where $$$r-l = l-p$$$ and $$$s_l=1, s_r=0$$$, we can apply an operation of length $$$r-l$$$ on $$$p$$$ and $$$l$$$, thereby eliminating both $$$p$$$ and $$$l$$$ simultaneously.
For other cases, we can show that there is always a method to eliminate until only one $$$1$$$ remains, and this remaining $$$1$$$ can only be at one of the positions $$$l, l-1, l-2, r, r+1, r+2$$$. This part can be resolved through case analysis.
Specifically, we only need to consider three cases: $$$A=B$$$, $$$A=B+1$$$, or $$$A=B-1$$$. If the case falls outside these three, such as $$$A',B',C'$$$, we always shift the interval inward and transform it into $$$A'-1, B'+2, C'-1$$$.
We take $$$F(B-1,B,B-1)$$$ as an example to discuss the specific method.
We further discuss based on $$$s_l$$$ and $$$s_r$$$. For convenience, we label the positions starting from $$$p$$$ as $$$0, \ldots, q-p$$$, and use a sequence to represent the positions operated on in order of decreasing length. Let the maximum available length be $$$L = q-p-2$$$. For example, the sequence $$$0,3,1$$$ means we first use an operation of length $$$L$$$ on $$$p$$$ and $$$p+L$$$, then use an operation of length $$$L-2$$$ on $$$p+3$$$ and $$$p+3+(L-2)$$$, and finally use an operation of length $$$L-4$$$ on $$$p+1$$$ and $$$p+1+(L-4)$$$.
- $$$s_l = s_r = 0$$$. We operate in order: $$$[0,1,2,\ldots,B-4], 2B-5, B-3$$$. Finally, a $$$1$$$ remains at index $$$B-2$$$.
- $$$s_l = 1, s_r = 0$$$. We operate in order: $$$0, [(3,2),(5,4),(7,6),\ldots,(B-3,B-4)], B-1, 1$$$. Finally, a $$$1$$$ remains at index $$$B-2$$$.
- $$$s_l = 0, s_r = 1$$$. We operate in order: $$$[0,1,2,\ldots,B-3], 2B-3$$$. Finally, a $$$1$$$ remains at index $$$B-2$$$.
- $$$s_l = s_r = 1$$$. We operate in order: $$$[1,2,3,\ldots,B-2], 0$$$. Finally, a $$$1$$$ remains at index $$$2B-2$$$.
Similarly, elimination methods for $$$F(B,B,B)$$$ and $$$F(B+1,B,B+1)$$$ can be obtained.
Thus, between every two adjacent $$$1$$$'s that cannot be eliminated, we can always save one elimination, leaving a $$$1$$$ within a distance of at most $$$2$$$ from $$$l$$$ or $$$r$$$. Let the interval length be $$$s$$$. Whenever a $$$1$$$ cannot be eliminated, $$$s$$$ becomes at least $$$\frac19 s + \frac{2}{3}$$$. Therefore, the number of remaining $$$1$$$'s is approximately $$$\log_9\frac{n}{2}+O(1)$$$. Note that when the interval length is small, it may consume many $$$1$$$'s. A constant optimization is that when the recursion interval length does not exceed $$$18$$$, we can use an $$$O(n^2 2^n)$$$ dynamic programming approach to easily find the optimal solution, and the optimal solution can always leave no more than $$$1$$$ remaining $$$1$$$. Additionally, there are other optimizations, such as running the algorithm forward and backward on the sequence and taking the better result. All of these can pass.
It can be proven that when $$$n \le 2 \times 10^6$$$, the total number of $$$1$$$'s does not exceed $$$7$$$.
#include<bits/stdc++.h>
using namespace std;
const int N=2e6,DB=20;
int n,a[N+1];
int ans[N+1];
int mid;
inline void op(int x,int y)
{
if(x>y)swap(x,y);
ans[y-x]=x;
a[x]^=1;
a[y]^=1;
}
inline void del(int x,int y)
{
if(x>y)swap(x,y);
if(!ans[y-x])return;
ans[y-x]=0;
a[x]^=1;
a[y]^=1;
}
#define ppc __builtin_popcount
namespace DP{
int n;
bool f[DB+1][1<<DB+1];
int g[DB+1][1<<DB+1];
void dp()
{
n=DB;
f[n][0]=1;
for(int S=1;S<(1<<n);S<<=1)f[n][S]=1;
for(int len=n;len>=2;len-=2)
{
for(int S=0;S<(1<<n);S++)
{
if(!f[len][S])continue;
f[len-2][S]=1;
g[len-2][S]=-1;
for(int i=0;i+len-1<n;i++)
{
f[len-2][S^(1<<i)^(1<<(i+len-1))]=1;
g[len-2][S^(1<<i)^(1<<(i+len-1))]=i;
}
}
}
}
vector<int>ask(int S)
{
int len=0;
vector<int>ans(n+2);
while(len<n)
{
int pos=g[len][S];
ans[len+1]=pos;
if(pos!=-1)
{
S^=1<<pos;
S^=1<<(pos+len+1);
}
len+=2;
}
return ans;
}
}
int solvec(int l,int r,int p)
{
if(!l)return p;
if(a[l]==a[r])
{
if(a[l])op(l,r);
return solvec(l-1,r+1,p);
}
if(p)op(p,p+r-l);
if(a[l])return solvec(l-1,r+1,l);
else return solvec(l-1,r+1,r);
}
void solvep(int l,int r,int p,bool flag)
{
if(l>=r)return;
if(!p)
{
if(a[l]==a[r])
{
if(a[l])op(l,r);
solvep(l+1,r-1,0,0);
return;
}
if(a[l])solvep(l+1,r-1,l,0);
else solvep(l+1,r-1,r,0);
return;
}
if(r-l+1==DB)
{
int S=0;
for(int i=l;i<=r;++i)S|=a[i]<<(i-l);
vector<int>res=DP::ask(S);
for(int len=r-l;len>=1;len-=2)
{
if(res[len]!=-1)op(res[len]+l,res[len]+len+l);
}
return;
}
int x=l+r-p,y=p;
if(x>y)swap(x,y);
int A=l-x,B=r-l+1;
int len=y-x-2;
auto f=[&](int a){int b=a+len;len-=2,a=a+x,b=b+x;if(p>l)a=l+r-a,b=l+r-b;op(a,b);};
if(!flag&&r-l+1>=10&&abs(A-B)==1)
{
for(int i=x+1;i<l;++i)del(i,l+r-i);
int type=a[l]|(a[r]<<1);
if(p>r)type=a[r]|(a[l]<<1);
if(A==B-1)
{
switch(type)
{
case 0:for(int i=0;i<=B-4;i++)f(i);f(2*B-5);f(B-3);break;
case 1:f(0);for(int i=3;i<=B-3;i+=2)f(i),f(i-1);f(B-1);f(1);break;
case 2:for(int i=0;i<=B-3;i++)f(i);f(2*B-3);break;
case 3:for(int i=1;i<=B-2;i++)f(i);f(0);break;
}
}
else if(A==B)
{
switch(type)
{
case 0:for(int i=0;i<=B-2;i++)f(i);f(2*B-1);break;
case 1:
if(B%3==2){f(1);f(0);for(int i=3;i<=B-5;i+=3)f(i+1),f(i+2),f(i);f(B-1);f(B);f(2);}
else if(B%3==0){f(1);f(0);for(int i=3;i<=B-6;i+=3)f(i+1),f(i+2),f(i);f(B-3);f(B);f(B-1);f(2);}
else{f(1);f(0);for(int i=3;i<=B-7;i+=3)f(i+1),f(i+2),f(i);f(B-3);f(B-4);f(B);f(B-1);f(2);}
break;
case 2:f(1);f(0);for(int i=3;i<=B-3;i+=2)f(i),f(i-1);f(B-1);f(2*B-2);break;
case 3:f(0);for(int i=3;i<=B-1;i+=2)f(i),f(i-1);f(1);break;
}
}
else if(A==B+1)
{
switch(type)
{
case 0:for(int i=1;i<=B;i++)f(i);f(0);break;
case 1:for(int i=1;i<B;i++)f(i);f(0);f(B);break;
case 2:for(int i=1;i<=B-1;i+=2)f(i),f(i-1);f(2*B);break;
case 3:
if(B%3==2){f(0);f(1);for(int i=3;i<=B-2;i+=3)f(i+2),f(i),f(i+1);f(2);}
else if(B%3==0){f(1);f(0);for(int i=3;i<=B-3;i+=3)f(i+1),f(i+2),f(i);f(B);f(2);}
else{f(1);f(0);for(int i=4;i<=B-3;i+=3)f(i),f(i+1),f(i-1);f(B);f(B-1);f(2);}
break;
}
}
for(int i=x;i<=l;++i)if(a[i]){solvep(l+1,r-1,i,1);return;}
for(int i=r;i<=y;++i)if(a[i]){solvep(l+1,r-1,i,1);return;}
solvep(l+1,r-1,0,1);
return;
}
if(a[l]&&a[r])
{
op(l,r);
solvep(l+1,r-1,p,flag);
return;
}
len=r-l;
auto down=[&](){
if(a[l])solvep(l+1,r-1,l,0);
else if(a[r])solvep(l+1,r-1,r,0);
else solvep(l+1,r-1,0,0);
};
if(p+len>l&&p+len<r)
{
op(p,p+len);
down();
return;
}
if(p-len>l&&p-len<r)
{
op(p,p-len);
down();
return;
}
down();
}
int rn;
void solve()
{
cin>>n;
rn=(n>>1);
for(int i=1;i<=n;++i)
{
char ch;
cin>>ch;
a[i]=ch-'0';
}
for(int i=1;i<=n;++i)ans[i]=0;
if(!(n&1))
{
op(n-(n>>1),n);
--n;
}
mid=(n+1>>1);
if(!(mid&1))--mid;
int p=solvec((mid>>1),(mid>>1)+2,(a[(mid>>1)+1]?(mid>>1)+1:0));
solvep(mid+1,n,0,0);
for(int i=1;i<=rn;++i)cout<<ans[i]<<' ';
cout<<'\n';
}
int main()
{
DP::dp();
int T;
cin>>T;
while(T--)solve();
return 0;
}








Auto comment: topic has been updated by wangmarui (previous revision, new revision, compare).
really awesome contest , this is like my favourite contest ever i really enjoyed the problems ; ; i was like stuck on b cause my dumbass wanted to speed blitz ab to try c ;; so ended up stuck in b for almost whole contest .... ;
Awesome contest , thank you
This contest was considerably harder to me, is it div.2 level or div.2+div.1? In any case, good job on the problems, they were well defined and I liked them.
really amazing of a contest i wish i could solve D1 i did get the intuition of pairwise connected components belonging to different subsets but couldnt really solve it properly. Loved the contest tho!
H: The QI condition is definitely false if we only group together the negative prefix, e.g. take A = -100 1 1. Then, cost [-100, 1, 1] + cost [1] << cost[-100, 1] + cost[1, 1]. Instead, we need to extend our prefix until the QI condition holds (equivalently, extend it to the global optimum), and then we can run the Knuth-optimization code.
sry you're right I just find a mistake in my prove that the s_b could be a huge negative number I will fix it soon
Actually I wanted to hack this.wrong code at first. To my relief,the data is still right
There's a way to make the solution work while only excluding negatives. Note that all transitions that start at positive values are Monge. Then, we can exclude the $$$a=0$$$ transitions from the monotonicity logic and run LARSCH on the later start points, and then min with the $$$a=0$$$ transition outside the LARSCH/Monge/monotonicity.
You can also run the dp backwards, so that only positive values are considered in the dp. To get the final answer, iterate through all $$$i$$$ as the break point of the segment containing negative values. Since the dp gets the answer for every prefix (or suffix in the original sense), it's easy to get the answer in $$$O(n)$$$.
Can someone please explain in B, why for k — 1, anything greater than or equal to k−1 are invalid, is it because to maximize the MEX, we need to keep the elements less than sequence length in the array?
Yes at the end we will be left with only k-1 elements so desired elements would be 0,1,2..k-2
To make MEX ≥ k, the array must contain all numbers from 0 to k−1, but the problem’s constraint limits this, so any MEX ≥ k is invalid and the maximum allowed value is k−1.
I used a different thought-process for D1, although I do believe it's more or less the same as what the editorial talks about: -
It is easy to observe that for any particular depth $$$d$$$, no two nodes can belong to the same set (as per the problem statement). Therefore, if we let $$$N_d$$$ be the count of nodes at depth $$$d$$$, we must make at least $$$N_d$$$ moves. This leads to our first lower bound being
Now consider a specific node $$$u$$$. We know that: -
This implies that $$$u$$$ and all its children form a clique where every node should be part of a unique set. This gives us our second relation
Combining these two necessary conditions, the optimal answer is simply the maximum of these two values. Hence we arrive at our final relation
I hope this helps! :)
Submission Link
how do you write those mathy terms like that inequalities and stuff in comments??
by using LaTeX, it helps in making things more elegant and easy to explain!
Love that explanation. Not that much different from the original but much clearer in my opinion. I should have thought of that :(
thanks for your kind words!
Love the idea. However, without thinking about the construction strategy in editorial, how did you prove that the minimal answer given by the two inequalities is also achievable?
Auto comment: topic has been updated by wangmarui (previous revision, new revision, compare).
Problem C can be solved faster in $$$O(t)$$$ time ($$$O(1)$$$ time per test case):
Let $$$s_1 = max(n-k, k-1)$$$ and $$$s_2 = min(n-k, k-1)$$$. You can first try to fill the same amount in both sides $$$x$$$, which takes $$$3 * x - 1$$$ days: $$$x-1$$$ days to get the soldiers for one side, $$$x$$$ days to fill this first side, and $$$x$$$ days to fill the second side. Solving for $$$x$$$ in this specific case gives us $$$\frac{m+1}{3}$$$, and we will thus fill $$$1 + 2*\frac{m+1}{3}$$$ bases in this case.
However in the case that $$$x \geq s_2$$$, you still take $$$3*s_2 - 1$$$ time to fill $$$s_2$$$ bases on both sides, but you add $$$2$$$ days for each base you want to cover on the second longer side, because you need to wait one day to get the extra soldier and you need one more day to reach one base farther at the end. The time you have at this point is $$$m - (3*s_2 - 1)$$$. Divide this by two and you get your extra reach. Thus the final formula is $$$1 + 2 * s_2 + min(s_1 - s_2, \frac{m - 3 * s_2 + 1}{2})$$$.
I'm not entirely sure if this approach is correct, but it got me an AC so I assume it is.
yeah I did this in contest but I used a while loop to check for the x (I called it lenpath) so it was actually O(n) instead of O(1) but could easily be reduced to O(1) 356828614
i normally recieve downvotes but im not even sure what i did to get them this time
Auto comment: topic has been updated by wangmarui (previous revision, new revision, compare).
I didn't find E as easy as >1200 AC
This may be because the transformation of E is relatively common in Chinese mathematics.
Alternative solution for C using Binary Search: -
Let $$$F(S)$$$ be a boolean function that returns true if it is possible to fortify $$$S$$$ forts within the given time limit $$$M$$$. It is easy to observe that if a valid configuration of $$$S$$$ forts exists, we can trivially achieve a configuration of $$$S-1$$$ forts by simply removing the soldier at the furthest fortified node. Thus, the function $$$F(S)$$$ is monotonic, allowing us to use Binary Search for the maximum $$$S$$$.
Now consider how to optimally distribute $$$S$$$ fortified forts. We know that: -
To minimize the time required, we should balance the expansion as much as possible. Let $$$L_{cap} = K-1$$$ and $$$R_{cap} = N-K$$$ be the capacities of the left and right sides. We attempt to assign $$$P = \lfloor \frac{S-1}{2} \rfloor$$$ soldiers to each side.
The actual number of forts we can fill on each side is bounded by the capacity: -
The optimal way to fortify these is to prioritize the side that requires more soldiers to maximize the utility of the spawner while traveling. Let: -
This leads to our fundamental relation for the number of days used: -
We must also account for specific edge cases: -
If $S$ is even (i.e., $$$S-1$$$ is odd), we need 1 extra soldier on one side, costing $$$2$$$ extra time units (wait + travel).
If $$$P \gt \text{capacity}$$$ for any side, we cannot extend further on that side. This forces us to send those soldiers to the other side (or wait), adding a penalty cost of $$$2 \cdot (P - \text{capacity})$$$.
Combining these conditions, we simply check if the calculated $$$\text{Moves} \le M$$$ to update our binary search boundaries.
I hope this helps! :)
Submission Link
Damn, this is exactly my solution, Niceee
Nahh, but mine was simpler tho, no specific edge cases, check my submission
true! you've implemented it in quite a simple manner, very cool!
Guys in the editorial's approach for C, a can take values in [0;k — 1] and b can take values in [0;n — k] so shouldn't we check for all k * (n — k + 1) possibilities. Whats the reason behind trying to increment a and b in turns and how does that work
Checking k*(n-k+1) possiblities is too slow as it can easily become O(n^2) (take k=n/2, then we have about n/2*n/2=n^2/4=O(n^2) possibilities to check
Yea I got that it's too slow but we do need to prove that the faster way is correct because we do have problems where exponential solution is the fastest. I was thinking of a generalization of this problem. Let's say we are trying to find the largest subarray containing a given element which satisfies some condition (that condition should be evaluated in constant time)(in this problem that element is k th position and that condition is a + b + max(a,b) — 1 <= m.) my doubt is whether there whether it's possible to solve this in O(n). If so can u please explain it with proof of correctness? Thanks
There are multiple solutions: First of all you could speed up the brute force by setting b and the binary searching for the optimal a in O(n log n), which would prob already pass.
The next improvement is our turn-based approach. The main assumption is, that you always want to keep |a-b| as small as possible. I find it hard to formalize this, but maybe this idea helps: For a given sum a+b (our "score") lets try to keep the term a+b+max(a,b)-1 as small as possible. The part a+b-1 is constant, so we have to try and minimize max(a,b), which is given exactly if |a-b| is minimal (This is kinda intuitive I hope). Now we can always try to increase the lower one of a,b if possible in each step, so |a-b| gets minimal (this is basically done in the editorial approach). You can also do it in O(1) per query by doing some casework. I hope this helps.
is it somehow possible to solve problem E with Cauchy–Schwarz inequality?
The algebra I worked out is below.
1/a + 1/b >= 1/c
c = arr[i-1]
a = lcm(arr[i],arr[i-1])
b = arr[i]
if (c * (b+a)) >= b*a: ## valid
i was super confused about D1. i couldn't see how one solves D1 without figuring out the solution for D2. and the editorial seems to suggest that D1 should be just guessed. i think this problem is promoting bad problem solving practices, and i don't understand why this problem needed to have subproblems.
Since problems A and B both rely heavily on guessing, I tried to keep using some kind of greedy approach in D as well, hoping to simulate the answer of D1 from D2. However, the acceptance rates between D1 and D2 really confuse me.
Does D1 actually have some obvious conclusion about the number of operations, but one that’s hard to turn into a concrete solution for D2? I asked myself, but the answer was no.
I feel like anyone who can solve D1 should also be able to solve D2 — maybe it’s just a matter of implementation time? But it doesn’t even seem that hard to implement.
During the contest, in order to move fast, I relied a bit too much on some unjustified guesses in problems A and B. Anyway, thanks to the problem setters for a great contest!
Although I agree with you and I used D1 just to confirm that my Hall's theorem argument was correct, that's the current cf meta.
oh. please tell me about your hall's theorem argument! because in that case indeed such a solution would not pass D2 but is enough to pass D1. i just went straight for a lower bound and a constructive upper bound.
Start the solution from knowing that (bipartite) matching solves the problem.
Construct the matching layer by layer. It's obvious that maximizing the number of things matches is optimal and we never need to unmatch shit because when going to the next layer each unmatched node is connected to all nodes on the other side.
Now to find the max match we use the min cut max flow theorem. By using middle edges with infinity capacity, a candidade for min cut can be obtained by fixing a set of nodes from the upper layer. After fixing a set of such nodes, the cut has capacity (sum of unchosen nodes from the upper layer) + (sum of nodes from the lower layer that are connected to chosen nodes). The trick in this sort of common "complement graph bipartite matching" thing is that if we take 2 different nodes the "sum of nodes from the lower layer" is the whole layer, so there are 3 types of cuts to be considered: empty set, full set, set of size 1. For the set of size 1 we take the node in the upper layer that has the most children in the tree.
After confirming that I didn't make a dumb mistake on D1 it was a matter of finding a greedy construction for the D2 solution.
Could you please explain how did you transform this problem to bipartite matching?
I've never before seen such a nice use of bipartite matching, so finding it difficult to relate.
You can reduce the problem into "find the min number of paths in a DAG to cover all vertices" and that's a very very very very well known bipartite matching problem that I might've seen 50+ times.
Actually, I think you can also use Dilworth's theorem to get the result more directly. Evidently, any antichain either contains only nodes from layer $$$i$$$, or some nodes from layers $$$i$$$ and $$$i + 1$$$. In the second case, it can only contain one node on layer $$$i$$$, and all the chosen nodes on layer $$$i + 1$$$ must be children of that node. From this, you can get the desired bound.
yeah, I think D1 is the worst problem I've seen in a Codeforces contest in at least the past few months, probably longer because this was an intentional decision... I don't understand how it was decided that this was fine. did a problem need replacing at the last minute, and they had no choice besides slotting a hard problem in D and finding some way to split it into two subtasks?
While we are on the topic of problem D, this guy is obviously cheating (check out all his submissions on it, switches languages, very diff style, etc): https://codeforces.me/contest/2183/submission/356826472
I think figuring out the solution for D2 is easier than actually implementing it. Maybe that’s why the author decided to include subproblems, so people who understand the logic but can’t implement it fully can at least solve D1.
Here, here, here, here, here
Amazing contest
Great contest i think, especially problem D2
A typo in Tutorial (zh) Page 11, Problem E,Hint4.
It should be:
If $$$y \gt x$$$ and $$$gcd(x,y)=y−x$$$
But:
If $$$x \gt y$$$ and $$$gcd(x,y)=y−x$$$
Auto comment: topic has been updated by Network_Error (previous revision, new revision, compare).
I liked H. Been practicing dp tasks. Loved it. Hoks_ !!
Auto comment: topic has been updated by Network_Error (previous revision, new revision, compare).
Auto comment: topic has been updated by Network_Error (previous revision, new revision, compare).
There is a way to avoid any case analysis for G. Every two consecutive positions which are still alive after
LRshouldn't be too far apart. So just brute force through all possible scenarios between some two consecutive elements and get the results beforehand. When answering a query, use the results given to find the actual speeds in the stuffs calculated before.how to do C in O(1)?
356791462
I misread B in virtual contest and thought the final sequence was length k rather than k-1, which makes it a lot harder. I'm curious if there is a solution to this harder variant?
Can anybody explain in E in solution how does last term (gcd(an,a1)/a1*an) becomes a1/an*a1 , shouldnt it be (an-a1)/an*a1
gcd(a1, an) <= a1
We decided to use two different inequalities. Can we get relation using only one to get same final observation
The reason for using a different inequality was so that you can cancel the 1/an and be left with 1/a1. Hence, we are able to prove it is <= 1 because a1 >= 1
because $$$\gcd(a_1,a_n)\le a_1$$$,so partial order relation remains unchanged
Amazing Problems! Thank for the great round! Really enjoyed the problems!
You will solve C quickly if you've played generals.io.
Alternative solution for problem F. It comes more from intuition than from strict math.
Notice:
Since constraints are <= 3000, try DP with N * M states. Most obvious state is a pair of current index i and current value a[i]. Because sum is max 1, just store 2 numbers for each DP state:
There are O(N * M) states, but complexity is O(N ^ 2 * M), because we have M transitions (iterating a[i + 1] possibilities for current i and a[i]). When solving small samples by hand, we noticed that with increase of a[i + 1], final sum decreases very fast. Thus, there are not many good a[i + 1] for given a[i]. Say a[i + 1] = a[i] + x, here if x is not a divisor of a[i], lcm(a[i], a[i + 1]) grow a lot and we likely never reach sum 1. So, iterate only x's which are divisors of a[i].
That's exactly what the editorial solution actually does, it just also contains a proof of this working.
Editorial contains a lot of math. I've just showed how to come to a valid solution via less math. Path to solution is different.
Implementation is also different actually. My DP produces 2 outputs:
- Max reachable sum of 1/lcm's.
- Number of ways to construct exactly the above-mentioned sum of 1/lcm's.
And I calculate the first of them just straightforward in "double" type variable. Editorial solution seems to calculate "number of ways" without calculating the max 1/lcm's sum.Editorial does math to come up to:
The equality holds if and only if gcd(ai,ai+1)=ai+1−ai for all 1≤i<n, and a1=1. Thus, the problem is transformed into counting the number of sequences that satisfy these conditions.
I don't do anything like this, but operate directly with LCM.
Problems C and D1 would be much harder without the test cases.
is there a more intuitive proof for C's necessity
Shouldn't A be Alice and Bob, not Yes and No?
For the problem
BI understand that in the end, the array will have k-1 elements so the final MEX <= k-1, if any number from 0 to k-2 isn't in the array, then it's the final mex.
But this still doesn't sound satisfactory to me. Can anyone kindly tell me an intuitive way to think about B?
The main observation is that you can end up with any $$$k-1$$$ numbers in the array, because in every step, you have an option to remove one number from $$$k$$$ numbers, and since you're only trying not to remove $$$k-1$$$ numbers, you always have an option to remove a number you don't care about. So the answer is just the maximal MEX among any $$$k-1$$$ numbers. Then, it's clearly optimal to first take a $$$0$$$, then $$$1$$$, $$$2$$$, etc., unless you either get to a number not in the starting array (in which case the answer is MEX of the starting array) or you use all $$$k-1$$$ spots (in which case the answer is $$$k-1$$$.
The "you always have an option to remove a number you don't care about" really help me to understand the solution. Thanks a lot
Auto comment: topic has been updated by jiazhichen844 (previous revision, new revision, compare).
Auto comment: topic has been updated by jiazhichen844 (previous revision, new revision, compare).
Can anyone explain problem B? I didn't understand...
See here.
Can anyone tell where I am going wrong ? My submission
I looked at your code, and you seem to have overcomplicated things a bit. The question is esentially How far can soldiers expand in m days from position k?
Also, you hardcoded your cases for small n, when a general formula of
answer = min(n, m+1, 1+min(m, k-1) + min(m, n-k)
works.
Thanks
难:)
E is such an amazing prblem! I cant help but admire the person who set this problem
I solved 3 questions but my question how could one correctly give a solution with proof during the contest as most of times I dont know if my solution is correct or not and also the proofs in the editorial look very non-trivial, pls tell what to do?
Also is there some other solution for problem E other then the one given in the editorial and also how would one think intuitively of the solution that was given in the editorial?
Auto comment: topic has been updated by Hoks_ (previous revision, new revision, compare).
can anyone tell a better or more easily comprehendable solution of F?
dp[u][v] = answer for the problem and the current "heads" of the paths are in u, v.
$$$dp[u][v] = \sum_{a \space child \space of \space u} dp[a][v] + \sum_{b \space child \space of \space v} dp[u][b] - [str[u] \neq str[v]] \sum_{a \space child \space of \space u} \sum_{b \space child \space of \space v} dp[a][b]$$$
That straightforward dp (think of that sort of count common subsequences dp on an array to understand why the — is there for managing double counting) is quadratic because for state (u, v) we do one transition per pair of edges going down u and v, so the total number of transitions is just the number of pairs of edges which is O(N^2).
Auto comment: topic has been updated by Hoks_ (previous revision, new revision, compare).
In div2C explanation, there's some confusion regarding claim 1. I think correct version should go like this:
"Consider a soldier at x starting from k and moving to x; it must pass through base y along the way. Consider making this soldier stop exactly at y . Then soldier x ends up at y .". Also for clarity, it's worth mentioning that k always ends up containing a soldier in the end.
By the way, how this remark
(If the move is not to the leftmost positions but to some intermediate positions, we can show through adjustment that such a move is suboptimal. Therefore, an optimal solution will not contain such moves.)
can be proven? Is it really suboptimal or only the swapping doesn't make the answer worse? I can't find a counterexample which would show that.
One more doubt which I have, the proof assumes it's optimal to fill leftmost contigous interval and doesn't consider the case where it might be gaps (I know it's intuitive, but still, no proof for that). And I'm not sure if h(S1)-h(S0)>=a-t is correct. Considering we start from t soldiers at k (the only occupied base), after a-t moves, we'll have 2 bases occupied (k and k-a+t, although it's not a part of our goal and could be occupied before) instead of 1 (k-th), while soldiers count will indeed grow by a-t. So I think the h delta should be >=a-t-1 (and I don't think we need > sign here, as we constantly have to move during this phase to k-a+t and each turn, the soldiers count grow by 1?).
Auto comment: topic has been updated by Hoks_ (previous revision, new revision, compare).
hope I just fixed everything
It was an awesome contest...since I am a beginner I felt overwhelmed but still managed to get one of them...but I want to know exactly how should I approach for these types of contest...kindly guide me through this journey...it would be a great help.
Great contest, I was only able to solve the A problem but I hope to get better :)
I didn’t really like the official explanation for H, so here is an alternative one.
Observations
As shown in the editorial, there exists an optimal solution where the partition consists of contiguous subarrays after sorting $$$a$$$. We work on the sorted array.
Let ($$$m$$$) be the number of non-negative elements.
Case 1: $$$(m \gt k)$$$:
We can put each non-negative element into its own group and keep all negatives in one prefix.
The optimal partition is: one group containing the first $$$(n-k+1)$$$ elements, and the remaining elements as singleton groups.
Case 2: $$$(m \le k):$$$
All negative elements should belong to a single group, so there is at most one prefix segment containing negatives (and possibly some positives).
We apply Alien’s trick. Introduce a penalty ($$$\lambda$$$) per segment and define
$$$ dp_\lambda[i] = \min_{j \lt i}\left(dp_\lambda[j] + (s[i]-s[j])\cdot(i-j) + \lambda\right), $$$ where ($$$s$$$) is the prefix sum of the sorted array.
For the transition cost
$$$ f(l,r) = dp_\lambda[l] + (s[r]-s[l])\cdot(r-l), $$$ we have the Monge property for indices $$$(l,r \ge n-m)$$$:
$$$ \forall a \le b \le c \le d:\quad f(a,c) + f(b,d) \le f(a,d) + f(b,c), $$$ since all involved values are non-negative and the $$$(dp_\lambda)$$$ terms cancel.
Negative elements are handled separately. Since they appear in at most one prefix segment, we start transitions from index (n-m+1) and additionally relax
$$$ dp_\lambda[i] \leftarrow \min(dp_\lambda[i], f(0,i) + \lambda). $$$
Thus, DP transitions satisfy the Monge property and can be optimized with standard 1D/1D optimization trick to solve in $$$O(n \log n)$$$ which you can read online.
The first 2 hints for H are kinda useless since $$$n=k$$$ is just sum. Better to go for
only negative and only positive numbers
I think the problemsetter meant to say “Consider how to solve the problem if n,k<=500” instead of n=k=500
Would make more sense to just say $$$n = 500$$$ in that case since $$$k \le n$$$. Well, if meaning is unclear, that just highlights the necessity of making hints' meaning clear instead of letting readers engage in exegesis.
ty
Auto comment: topic has been updated by Hoks_ (previous revision, new revision, compare).
i would like to respectfully express my frustration at the implementation for D2. looking at the code makes me want to look away. upsolving is hard enough when im this sleepy
I found tin_le's implementation much easier to understand: https://codeforces.me/contest/2183/submission/356818803
Auto comment: topic has been updated by Network_Error (previous revision, new revision, compare).
Brilliant problems! However, However, I still have a question regarding the proof for Problem H.
In the part of proving QI, why does the inequality $$$bs_b-(b-1)s_{b-1}\ge 0$$$ hold even when only $$$a_1$$$ is negative. If $$$a=[-100,1]$$$ and $$$b=2$$$, for instance, the condition does not seem to be satisfied.
I remember I'very changed the prove to the new right version In current version,We define k as the largest k satisfying the partition being optimal for the preceding part. So in your example -100 and -1 must be in the same part so we don't consider position 2 so that the QI holds. In fact, even if the QI in the previous version was incorrect, the dp within it can still be optimized to be less than O(n^2). But as for me,without QI just hard to prove it could use Alien's Trick
Yes, thanks.
Was upsolving and found some solutions with O(1) time in Problem C. Can someone explain how the math is working?
there is a mistake in problem E, LCM is not legendary counting master, its actually me(LegendaryCandidateMaster)
jk jk this was a great contest thank you!
Thank you wangmarui for contest and problem.
problem I. I haven’t even proved that the final score is $$$\leq 7$$$, but my solution still got accepted even with $$$\leq 3$$$. https://codeforces.me/contest/2183/submission/363500243
Is there a proof on I1?
Implementation for problem A should print
Aliceinstead ofYESandBobinstead ofNO.Damn ... E is such a good problem
Auto comment: topic has been updated by Hoks_ (previous revision, new revision, compare).