传送门(easy version)
传送门(hard version)
题意
思路
(easy version)
对于easy版本来说我们只需要明白一点:我们只需要求出最少的删除数字的个数,而且还有一点值得注意的是:删除某个数字以后,后面的位置对求和以后的贡献正好是倒转的,(正变负,负变正),因此我们先按照答案要求的来模拟,最后得到的数据,如果是0,那么我们的答案就是0(不用删除就可以完成结果),但是如果最后的答案不是0,如果结果是奇数,那么我们只需要删除一个,也就是 A-A结构,A和后面的A对答案数值贡献的是一样的,但是中间的-则对答案数值贡献的情况只有1,因此删掉这个,后面的A就可以把前面的全部数值抵消。
如果是偶数,那么我们则需要多加一步就是把答案转换成为奇数的情况因此是2步。
#include <iostream>
#include <string>
using namespace std;
int sum[2102100];
int main()
{
int T;
cin >> T;
while (T--)
{
int n, q;
cin >> n >> q;
string s;
cin >> s;
int ans = 0;
for (int i = 1, j = 1; i <= n; i++, j *= -1)
{
if (s[i - 1] == '+')
{
ans = 1 * j;
}
else
ans = (-1) * j;
sum[i] = sum[i - 1] + ans;
}
while (q--)
{
int l, r;
cin >> l >> r;
if (sum[r] == sum[l - 1])
{
cout << "0" << endl;
continue;
}
int p = sum[r]-sum[l-1];
if (p % 2 == 0)
{
cout << "2" << endl;
}
else
cout << "1" << endl;
}
}
}
(hard version)
这个hv比ev难得一点就是你要找出来你要删除的那个数,也就是临界值,这个临界值怎么找,仍然是我们刚刚的做法:
A-A找出 -
但是这样的做法我们只能使用
O
(
n
2
)
O(n^2)
O(n2)的暴力枚举,我们很难做到非常这样,因此我们需要用一个二位动态矩阵,来存储所有出现过的下标(因为我们知道这个值一定是
0
0
0到
2
n
−
1
2n-1
2n−1)又因为下标是单调递增的,因此可以考虑二分。
S
U
M
[
L
−
1
]
+
(
S
U
M
[
R
]
−
S
U
M
[
L
−
1
]
)
/
2
+
1
SUM[L-1]+(SUM[R]-SUM[L-1])/2+1
SUM[L−1]+(SUM[R]−SUM[L−1])/2+1的那个数。
如果是偶数,那么就先删除成为奇数,再去搞一搞~
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int sum[2102100];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--)
{
int n, q;
cin >> n >> q;
vector<vector<int> > vec(2 * n + 1);
string s;
cin >> s;
int ans = 0;
for (int i = 1, j = 1; i <= n; i++, j *= -1)
{
if (s[i - 1] == '+')
{
ans = 1 * j;
}
else
ans = (-1) * j;
sum[i] = sum[i - 1] + ans;
vec[sum[i]+n].push_back(i);
}
while (q--)
{
int l, r;
cin >> l >> r;
if (sum[r] == sum[l - 1])
{
cout << "0" << endl;
continue;
}
int p = sum[r] - sum[l - 1];
if (p % 2 == 0)
{
cout << "2" << endl;
cout << r << " ";
p = sum[r - 1] - sum[l - 1];
if (p < 0)
p = sum[l - 1] + p / 2 - 1;
else
p = sum[l - 1] + p / 2 + 1;
int t = *lower_bound(vec[p + n].begin(), vec[p + n].end(), l);
cout << t << endl;
}
else
{
p = sum[r] - sum[l - 1];
cout << "1" << endl;
if (p < 0)
p = sum[l - 1] + p / 2 - 1;
else
p = sum[l - 1] + p / 2 + 1;
int t = *lower_bound(vec[p + n].begin(), vec[p + n].end(), l);
cout << t << endl;
}
}
}
}