题目链接
1753A1 - Make Nonzero Sum (easy version) Rating:1300
题目描述
This is the easy version of the problem. The difference is that in this version the array can not contain zeros. You can make hacks only if both versions of the problem are solved.
You are given an array
[
a
1
,
a
2
,
…
a
n
]
[a_1,a_2,…a_n]
[a1,a2,…an] consisting of integers −1
and 1
. You have to build a partition of this array into the set of segments
[
l
1
,
r
1
]
,
[
l
2
,
r
2
]
,
…
,
[
l
k
,
r
k
]
[l1,r1],[l2,r2],…,[lk,rk]
[l1,r1],[l2,r2],…,[lk,rk] with the following property:
- Denote the alternating sum of all elements of the i-th segment as si: s i = a l i − a l i + 1 + a l i + 2 − a l i + 3 + … ± a r i si = ali−ali+1+ali+2−ali+3+…±ari si=ali−ali+1+ali+2−ali+3+…±ari. For example, the alternating sum of elements of segment [2,4] in array [1,0,−1,1,1] equals to 0−(−1)+1=2.
- The sum of si over all segments of partition should be equal to zero.
Note that each s i s_i si does not have to be equal to zero, this property is about sum of si over all segments of partition.
The set of segments [ l 1 , r 1 ] , [ l 2 , r 2 ] , … , [ l k , r k ] [l1,r1],[l2,r2],…,[lk,rk] [l1,r1],[l2,r2],…,[lk,rk] is called a partition of the array a of length n if 1 = l 1 ≤ r 1 , l 2 ≤ r 2 , … , l k ≤ r k = n 1=l1≤r1,l2≤r2,…,lk≤rk=n 1=l1≤r1,l2≤r2,…,lk≤rk=n and r i + 1 = l i + 1 ri+1=li+1 ri+1=li+1 for all i = 1 , 2 , … k − 1 i=1,2,…k−1 i=1,2,…k−1. In other words, each element of the array must belong to exactly one segment.
You have to build a partition of the given array with properties described above or determine that such partition does not exist.
Note that it is not required to minimize the number of segments in the partition.
Input
Each test contains multiple test cases. The first line contains the number of test cases t ( 1 ≤ t ≤ 10000 ) t (1≤t≤10000) t(1≤t≤10000). Description of the test cases follows.
The first line of each test case contains an integer n ( 1 ≤ n ≤ 200000 ) n (1≤n≤200000) n(1≤n≤200000) — the length of the array a.
The second line of each test case contains n integers a 1 , a 2 , … , a n ( a i i s − 1 o r 1 ) a1,a2,…,an (ai is −1 or 1) a1,a2,…,an(aiis−1or1) — the elements of the given array.
It’s guaranteed that the sum of n over all test cases does not exceed $200000.
Output
For each test case, if required partition does not exist, print −1
. Otherwise, print an integer k — the number of segments in the partition.
Then in the i-th of the following k lines print two integers l i li li and r i ri ri— description of the i-th segment. The following conditions should be satisfied:
- l i ≤ r i li≤ri li≤ri for each i from 1 to k.
- l i + 1 = r i + 1 li+1=ri+1 li+1=ri+1 for each i from 1 to (k−1).
-
l
1
=
1
,
r
k
=
n
l1=1,rk=n
l1=1,rk=n
.
If there are multiple correct partitions of the array, print any of them.
inputCopy
4
4
1 1 1 1
6
-1 1 1 1 1 1
3
1 -1 1
1
1
outputCopy
1
1 4
2
1 3
4 6
-1
-1
大致题意:
每次给你一个长度为
n
n
n ,只包含 1
和 -1
的数组
a
a
a。
我们定义:区间和的计算方式为 a 1 ∗ 1 + a 2 ∗ ( − 1 ) + a 3 ∗ 1 + a 4 ∗ ( − 1 ) . . . . a1 * 1 + a2 * (-1) + a3 * 1 + a4 * (-1).... a1∗1+a2∗(−1)+a3∗1+a4∗(−1)....。
问的是能否将数组
a
a
a,分成一个或多个连续的区间(左端点和右端点可以相等,例如:
[
1
,
1
]
,
[
2
,
2
]
[1,1],[2,2]
[1,1],[2,2]…这些都是合法区间),所有的区间和加起来
s
u
m
=
0
sum = 0
sum=0。如果可以,就输出区间的个数,以及是哪些区间(返回任意合法答案即可);否则输出 -1
。
分析:
如果整个数组之和
s
u
m
sum
sum 是奇数的话肯定不会有答案,打印-1
即可。因为即使将原数组拆分成多个区间,也不会影响奇偶性。反之,
s
u
m
sum
sum 为偶数的情况下,
n
n
n 也为偶数,肯定有答案。
我们可以考虑 让拆分的每一个区间的和都为0。这样总的加起来也为0,满足要求。
我们可以将原数组拆分成两个数的区间 [ a 2 i − 1 , a 2 i ] [a_{2i-1},a_{2i}] [a2i−1,a2i]。
- 如果 a 2 i − 1 = = a 2 i a_{2i-1}==a_{2i} a2i−1==a2i,那么就直接加入此区间 [ a 2 i − 1 , a 2 i ] [a_{2i-1},a_{2i}] [a2i−1,a2i]。
- 否则加入两个区间, [ a 2 i − 1 , a 2 i − 1 ] [a_{2i-1},a_{2i-1}] [a2i−1,a2i−1] 和 [ a 2 i , a 2 i ] [a_{2i},a_{2i}] [a2i,a2i]
只有这样才能保证没一个区间和都是 0。
时间复杂度: O ( n ) O(n) O(n)
代码:
#include <iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
using PII = pair<int,int>;
const int N = 2e5+10;
int a[N];
void solve(){
int n;
scanf("%d",&n);
int sum = 0;
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
sum += a[i];
}
if(sum % 2){
puts("-1");
return;
}
vector<PII> ans;
for(int i = 1,j = 2;j <= n;i += 2,j += 2){
if(a[i] == a[j]){
ans.push_back({i,j});
}
else{
ans.push_back({i,i});
ans.push_back({j,j});
}
}
cout<<ans.size()<<endl;
for(auto &e:ans){
printf("%d %d\n",e.first,e.second);
}
}
int main() {
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}