本场比赛其他题目的题解
A. The Miracle and the Sleeper
B. Scenes From a Memory
C. Rings
D1. Two Hundred Twenty One (easy version)
D2. Two Hundred Twenty One (hard version)
D2. Two Hundred Twenty One (hard version)
题目描述
This is the hard version of the problem. The difference between the versions is that the hard version does require you to output the numbers of the rods to be removed. You can make hacks only if all versions of the problem are solved.
Stitch likes experimenting with different machines with his friend Sparky. Today they built another machine.
The main element of this machine are n n n rods arranged along one straight line and numbered from 1 1 1 to n n n inclusive. Each of these rods must carry an electric charge quantitatively equal to either 1 1 1 or − 1 -1 −1 (otherwise the machine will not work). Another condition for this machine to work is that the sign-variable sum of the charge on all rods must be zero.
More formally, the rods can be represented as an array of n n n numbers characterizing the charge: either 1 1 1 or − 1 -1 −1. Then the condition must hold: a 1 − a 2 + a 3 − a 4 + … = 0 a_1 - a_2 + a_3 - a_4 + \ldots = 0 a1−a2+a3−a4+…=0, or ∑ i = 1 n ( − 1 ) i − 1 ⋅ a i = 0 \sum\limits_{i=1}^n (-1)^{i-1} \cdot a_i = 0 i=1∑n(−1)i−1⋅ai=0.
Sparky charged all n n n rods with an electric current, but unfortunately it happened that the rods were not charged correctly (the sign-variable sum of the charge is not zero). The friends decided to leave only some of the rods in the machine. Sparky has q q q questions. In the i i ith question Sparky asks: if the machine consisted only of rods with numbers l i l_i li to r i r_i ri inclusive, what minimal number of rods could be removed from the machine so that the sign-variable sum of charges on the remaining ones would be zero? Also Sparky wants to know the numbers of these rods. Perhaps the friends got something wrong, and the sign-variable sum is already zero. In that case, you don’t have to remove the rods at all.
If the number of rods is zero, we will assume that the sign-variable sum of charges is zero, that is, we can always remove all rods.
Help your friends and answer all of Sparky’s questions!
Input
Each test contains multiple test cases.
The first line contains one positive integer t ( 1 ≤ t ≤ 1 0 3 ) t\ (1\le t \le 10^3) t (1≤t≤103), denoting the number of test cases. Description of the test cases follows.
The first line of each test case contains two positive integers n n n and q q q ( 1 ≤ n , q ≤ 3 ⋅ 1 0 5 1\le n, q\le 3⋅10^5 1≤n,q≤3⋅105) — the number of rods and the number of questions.
The second line of each test case contains a non-empty string s s s of length n n n, where the charge of the i i i-th rod is 1 1 1 if s i s_i si is the “+” symbol, or − 1 -1 −1 if s i s_i si is the “-” symbol.
Each next line from the next q q q lines contains two positive integers l i l_i li ans r i r_i ri ( 1 ≤ l i ≤ r i ≤ n 1\le l_i\le r_i\le n 1≤li≤ri≤n) — numbers, describing Sparky’s questions.
It is guaranteed that the sum of n n n over all test cases does not exceed 3 ⋅ 1 0 5 3⋅10^5 3⋅105, and the sum of q q q over all test cases does not exceed 3 ⋅ 1 0 5 3⋅10^5 3⋅105.
It is guaranteed that the sum of the answers (minimal number of rods that can be removed) over all test cases does not exceed 1 0 6 10^6 106.
Output
For each test case, print the answer in the following format:
In the first line print a single integer k k k — the minimal number of rods that can be removed.
In the second line print k k k numbers separated by a space — the numbers of rods to be removed.
If there is more than one correct answer, you can print any.
Example
Input1
3
14 1
+--++---++-++-
1 14
14 3
+--++---+++---
1 14
6 12
3 10
4 10
+-+-
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 3
3 4
4 4
Output1
2
5 8
2
1 11
1
9
0
1
1
2
1 2
1
2
2
1 3
1
2
2
2 3
1
3
1
3
2
3 4
1
4
Note
In the first test case for the first query you can remove the rods numbered 5 5 5 and 8 8 8, then the following set of rods will remain: ±-±-+±+±. It is easy to see that here the sign-variable sum is zero.
In the second test case:
- For the first query, we can remove the rods numbered 1 1 1 and 11 11 11, then the following set of rods will remain: --+±–+±–. It is easy to see that here the sign-variable sum is zero.
- For the second query we can remove the rod numbered
9
9
9, then the following set of rods will remain: —+±. It is easy to see that here the variable sum is zero.
For the third query we can not remove the rods at all.
题意
t t t 组用例。对于每组用例,给你一个长度为 n n n 的字符串 a a a 和 q q q 个询问。字符串保证只有 + 和 - 。
每次询问给你两个正整数 l , r l, r l,r,表示询问将 a [ l : r ] a[l: r] a[l:r] 这个字符串最少需要删掉几个字符,变成字符串 s s s,使得 s s s 满足 ∑ i = 1 s . l e n g t h ( ) ( s [ i ] = = + ? 1 : − 1 ) ∗ ( ( i & 1 ) ? 1 : − 1 ) = = 0 \sum_{i=1}^{s.length()} (s[i]==+?1:-1) * ((i\&1)?1:-1) == 0 ∑i=1s.length()(s[i]==+?1:−1)∗((i&1)?1:−1)==0。(用人话来说就是,奇数位加系数 1 1 1,偶数位加系数 − 1 -1 −1。+ 表示 1 1 1, - 表示 − 1 -1 −1 ,使得整个字符串和为 0 0 0 )。并输出删掉了哪些字符。
分析
由于这个题是 D 1 D1 D1 的加强版,所以 D 1 D1 D1 中的部分结论也同样适用于这个题目,如果你 D 1 D1 D1 没有通过的话,强烈建议先去把 D 1 D1 D1 过了,这是 D 1 D1 D1 的 题解。
首先,同样的,特判掉已经是答案的。偶数长度的转成奇数的情况即可。
所以本质上,这道题需要考虑的只有一个问题:对于一个长度为奇数的字符串,如何删除一个字符,使得值为 0 0 0。
通过 D 1 D1 D1 ,我们知道了 b 1 b_1 b1 和 b n b_n bn 一定一正一负,并且他们之间是近乎单调的(任意的 ∣ b i − b i + 1 ∣ = 0 o r 2 |b_i - b_{i+1}| = 0\ or\ 2 ∣bi−bi+1∣=0 or 2 。所以,我们对于这个序列,显然可以二分,找到那个为 0 0 0 的点。
代码写的并不好看,主要是思想比较重要,这个二分确实有惊艳到我。
为了避免大家没看懂,我简单解释下每个函数干了啥。
sign(a) : 判断a的正负号
cal(l, r) : 计算区间 [l,r] 的值
cal(l, r, mid) : 计算区间[l,mid-1]和区间[mid, r]的值的和
cal() : 处理每次请求
solve() : 处理每个case
#include<bits/stdc++.h>
using namespace std;
int n, q, l, r;
string a;
int suffix[300005];
int sign(int a) {
if (a == 0) return 0;
return a > 0 ? 1 : -1;
}
int cal(int l, int r) {
if (l > r) return 0;
return suffix[l] - suffix[r + 1] * ((r - l) & 1 ? 1 : -1);
}
int cal(int l, int r, int mid) {
int a = cal(l, r);
int b = 2 * cal(mid, r) * ((mid - l - 1) & 1 ? 1 : -1);
int c = cal(mid, mid) * (((mid - l + 1) & 1) ? 1 : -1);
return a - b + c;
}
int cal() {
if (l == r) return l;
int lval = sign(cal(l + 1, r));
int rval = sign(cal(l, r - 1));
if (lval == 0) return l;
if (rval == 0) return r;
assert(lval != rval);
int ll = l, rr = r;
while (ll + 5 < rr) {
int mid = (ll + rr) >> 1;
int midval = sign(cal(l, r, mid));
if (midval == 0) return mid;
if (midval == lval) ll = mid;
else rr = mid;
}
for (int i = ll; i <= rr; i++) {
if (cal(l, r, i) == 0) return i;
}
assert(false);
return -1;
}
void solve() {
cin >> n >> q >> a;
for (int i = a.length() - 1; i >= 0; i--) suffix[i + 1] = -suffix[i + 2] + (a[i] == '+' ? 1 : -1);
while (q--) {
cin >> l >> r;
if (suffix[l] == suffix[r + 1]) cout << 0 << endl;
else if ((r - l + 1) & 1) cout << 1 << ' ' << cal() << endl;
else {
cout << 2 << ' ' << l;
l++;
cout << ' ' << cal() << endl;
}
}
}
int main() {
cin.tie(NULL);
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) solve();
return 0;
}