D. Equal Binary Subsequences

D. Equal Binary Subsequences

Everool has a binary string s of length 2n. Note that a binary string is a string consisting of only characters 0 and 1. He wants to partition s into two disjoint equal subsequences. He needs your help to do it.

You are allowed to do the following operation exactly once.

You can choose any subsequence (possibly empty) of s and rotate it right by one position.
In other words, you can select a sequence of indices b1,b2,,bm, where 1b1<b2<≤<bm2n. After that you simultaneously set

sb1:=sbm,sb2:=sb1,,sbm:=sbm1

Can you partition s into two disjoint equal subsequences after performing the allowed operation exactly once?

A partition of s into two disjoint equal subsequences sp and sq is two increasing arrays of indices p1,p2,,pn and q1,q2,,qn, such that each integer from 1 to 2n is encountered in either p or q exactly once, sp=sp1sp2spn, sq=sq1sq2sqn, and sp=sq.

If it is not possible to partition after performing any kind of operation, report 1.

If it is possible to do the operation and partition s into two disjoint subsequences sp and sq, such that sp=sq, print elements of b and indices of sp, i. e. the values p1,p2,,pn.

Input

Each test contains multiple test cases. The first line contains the number of test cases t(1t105). Description of the test cases follows.

The first line of each test case contains a single integer n(1n105), where 2n is the length of the binary string.

The second line of each test case contains the binary string s of length 2n.

It is guaranteed that the sum of n over all test cases does not exceed 105.

Output

For each test case, follow the following output format.

If there is no solution, print 1.

Otherwise,

In the first line, print an integer m(0m2n), followed by m distinct indices b1,b2,,bm(in increasing order).
In the second line, print n distinct indices p1,p2,,pn (in increasing order).

If there are multiple solutions, print any.

Example

input

复制代码
4
2
1010
3
100010
2
1111
2
1110
复制代码

output

0
1 2
2 3 5
1 2 5
3 2 3 4
1 4
-1

Note

In the first test case, b is empty. So string s is not changed. Now sp=s1s2=10, and sq=s3s4=10.

In the second test case, b=[3,5]. Initially s3=0, and s5=1. On performing the operation, we simultaneously set s3=1, and s5=0.

So s is updated to 101000 on performing the operation.

Now if we take characters at indices [1,2,5] in sp, we get s1=100. Also characters at indices [3,4,6] are in sq. Thus sq=100. We are done as sp=sq.

In fourth test case, it can be proved that it is not possible to partition the string after performing any operation.

 

解题思路

  首先很容易知道有解的必要条件是01串中1的个数是偶数,下面证明这个条件也是充分的。

  我们尝试用以下方法来构造答案,每相邻两个字符为一组,因此可以分成n组,每组都是(s2i1,s2i)(1in)这个形式。现在假设组内两个元素不同的组有x个,那么组内两个元素相同的组有nx个。

  可以证明x一定是偶数。

  在组内两个元素相同的nx个组中,假设有y组两个元素都是1,那么整个01串中1的个数就是x+2y,由于整个01串中1的个数要为偶数,因此x+2y是一个偶数,即x是一个偶数。

  现在我们给x个两个元素不同的组进行编号[1nx],并在每组中按照以下规则选出一个元素:对于编号为奇数的组,我们在这组中选择1;对于编号为偶数的组,则选择0(当然也可以反过来,奇数组选0,偶数组选1)。这样我们就会得到一个大小为n20, 1, 0, 1, , 0, 1这样01交替的序列(所以前面证明x是偶数就可以保证这个序列中01的个数是相同的,因此可以实现01交替)。同时每组未被选择的元素就会构成1, 0, 1, 0, , 1, 0这样10交替的序列。

  这时我们就可以用顺时针偏移操作了,我们对选择出的0, 1, 0, 1, , 0, 1进行一次顺时针偏移,就会得到1, 0, 1, 0, , 1, 0,这就与每组未被选择的元素所构成的序列相同了。

  这时我们再对这两个序列进行组合,那么每组内的元素都是相同的了,即s2i1=s2i

  上面将x个两个元素不同的组通过顺时针偏移变成组内两个元素都相同,再加上本来的nx个两个元素相同的组,此时我们就可以保证每一组内两个元素都相同,这时我们只需要枚举每一组,然后选择每组第一个元素构成序列,就可以构造出两个完全相同的序列的。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 2e5 + 10;
 5 
 6 char s[N];
 7 
 8 void solve() {
 9     int n;
10     scanf("%d %s", &n, s + 1);
11     
12     int cnt = 0;
13     for (int i = 1; i <= n << 1; i++) {
14         cnt += s[i] & 1;
15     }
16     if (cnt & 1) {    // 01串中1的个数是偶数 
17         printf("-1\n");
18         return;
19     }
20     
21     vector<int> ans;    // 用来存放要进行偏移的下标 
22     for (int i = 1, t = 0; i <= n << 1; i += 2) {
23         if (s[i] != s[i + 1]) {    // 这一组内两个元素不相同 
24             // 根据0和1交替选择 
25             if ((s[i] & 1) == t) ans.push_back(i);
26             else ans.push_back(i + 1);
27             t ^= 1;
28         }
29     }
30     
31     printf("%d", ans.size());
32     for (auto &it : ans) {
33         printf(" %d", it);
34     }
35     printf("\n");
36     
37     for (int i = 1; i <= n << 1; i += 2) {
38         printf("%d ", i);    // 此时每组元素内两个元素都相同,选择组内第一个元素 
39     }
40     printf("\n");
41 }
42 
43 int main() {
44     int t;
45     scanf("%d", &t);
46     while (t--) {
47         solve();
48     }
49     
50     return 0;
51 }
复制代码

 

参考资料

  Codeforces Round #825 (Div. 2) Editorial:https://codeforces.com/blog/entry/107847

  Codeforces Round #825 (Div. 2) A~D:https://zhuanlan.zhihu.com/p/572387762

posted @   onlyblues  阅读(121)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示