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;
}








