easy version
题意
给定一个取值只有1,-1的数组,选取它的不重合不漏的子区间集si=[li,ri],使得si的总和为0。不要求选择的子区间集数量最小化。
子区间集S满足以下条件
- si = a[li] - a[li+1]+…+/-a[ri]
- r[i] +1 == l[i+1], 1<=i<n
- l[1]=1, r[k]=n
即每个数组上的值,刚好包含在一个子区间中。每个子区间的值的计算,是加、减交替的。
如果不存在这样的子区间集,输出-1;如果存在,输出这些子区间集。
思路
- 对于长度超过3的集合,a-b+c-… = (a+b) + c -…
即我们只需要把集合拆分成长度<=2的即可。 - 数组长度一定要为偶数,奇数的话,总和不可能为0。
- 两两相邻的元素,一定可以为0。
证明:如果a[i] == a[i+1],则让它们在一个组,这样si = a[i]-a[i+1]=0;如果如果a[i] != a[i+1],则让它们不在一个组,这样si +si+1=a[i]+a[i+1]=0
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pcc pair<char, char>
#define pii pair<int, int>
#define inf 0x3f3f3f3f
const int maxn = 200010;
int n, a[maxn];
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
if (n & 1) {
printf("-1\n");
return;
}
vector<pii> res;
for (int i = 1; i <= n; i += 2) {
if (a[i] == a[i+1]) {
res.push_back({i, i + 1});
} else {
res.push_back({i, i});
res.push_back({i + 1, i + 1});
}
}
int len = res.size();
printf("%d\n", len);
for (auto p: res) {
printf("%d %d\n", p.first, p.second);
}
}
int main() {
int t = 1;
scanf("%d", &t);
int cas = 1;
while (t--) {
// printf("cas %d:\n", cas++);
solve();
}
}
hard version
题意
同easy version ,区别是数组取值为-1,0,1。
思路
- 把0去掉后,看剩余个数,当且仅当剩余个数是偶数可行。
- 同easy version思路,相邻的2个不为0的数凑一对就行了。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pcc pair<char, char>
#define pii pair<int, int>
#define inf 0x3f3f3f3f
const int maxn = 200010;
int n, a[maxn];
void solve() {
scanf("%d", &n);
int s = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
if (a[i]) ++s;
}
if (s & 1) {
printf("-1\n");
return;
}
vector<pii> res;
int l, r;
for (int i = 1; i <= n;) {
// first
while (i <= n && !a[i]) {
res.push_back({i, i});
++i;
}
if (i > n) {
break;
}
l = i;
// second
r = i + 1;
if (a[r]) {
if (a[l] == a[r]) {
res.push_back({l, r});
} else {
res.push_back({l, l});
res.push_back({r, r});
}
} else {
res.push_back({l, l});
while (r <= n && !a[r]) {
res.push_back({r, r});
++r;
}
if (a[l] == a[r]) {
res.back().second = r;
} else {
res.push_back({r, r});
}
}
i = r + 1;
}
int len = res.size();
printf("%d\n", len);
for (auto p: res) {
printf("%d %d\n", p.first, p.second);
}
}
int main() {
int t = 1;
scanf("%d", &t);
int cas = 1;
while (t--) {
// printf("cas %d:\n", cas++);
solve();
}
}
GZH
对方正在debug