C1. Make Nonzero Sum (easy version)
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 [a1,a2,…an][a1,a2,…an] consisting of integers −1−1 and 11. You have to build a partition of this array into the set of segments [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 ii-th segment as sisi: sisi = ali−ali+1+ali+2−ali+3+…±ariali−ali+1+ali+2−ali+3+…±ari. For example, the alternating sum of elements of segment [2,4][2,4] in array [1,0,−1,1,1][1,0,−1,1,1] equals to 0−(−1)+1=20−(−1)+1=2.
- The sum of sisi over all segments of partition should be equal to zero.
Note that each sisi does not have to be equal to zero, this property is about sum of sisi over all segments of partition.
The set of segments [l1,r1],[l2,r2],…,[lk,rk][l1,r1],[l2,r2],…,[lk,rk] is called a partition of the array aa of length nn if 1=l1≤r1,l2≤r2,…,lk≤rk=n1=l1≤r1,l2≤r2,…,lk≤rk=n and ri+1=li+1ri+1=li+1 for all i=1,2,…k−1i=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.
Each test contains multiple test cases. The first line contains the number of test cases tt (1≤t≤100001≤t≤10000). Description of the test cases follows.
The first line of each test case contains an integer nn (1≤n≤2000001≤n≤200000) — the length of the array aa.
The second line of each test case contains nn integers a1,a2,…,ana1,a2,…,an (aiai is −1−1 or 11) — the elements of the given array.
It's guaranteed that the sum of nn over all test cases does not exceed 200000200000.
For each test case, if required partition does not exist, print −1−1. Otherwise, print an integer kk — the number of segments in the partition.
Then in the ii-th of the following kk lines print two integers lili and riri — description of the ii-th segment. The following conditions should be satisfied:
- li≤rili≤ri for each ii from 11 to kk.
- li+1=ri+1li+1=ri+1 for each ii from 11 to (k−1)(k−1).
- l1=1,rk=nl1=1,rk=n.
If there are multiple correct partitions of the array, print any of them.
Input
4 4 1 1 1 1 6 -1 1 1 1 1 1 3 1 -1 1 1 1
Output 1 1 4 2 1 3 4 6 -1 -1
题目大意就是给定一个数组a,元素可以为1或-1,我们的操作可以把这些元素分成任意个区间,一个区间里面的区间和满足这样的性质a1-a2+a3-a4.....,不同区间之间直接相加,求出是否存在划分使得所有区间相加最终结果为0
#include <iostream> #include <cstring> using namespace std; const int N=2e5+10; int t,n; int a[N],sum; bool p[N];//标记数组记录哪些数字和后一个数字是合并为同一个区间的 typedef struct{ int l,r; }node; node res[N]; int main(){ cin>>t; while(t--){ cin>>n; sum=0; memset(p,0,sizeof p); for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];//一开始求所有单区间的和,即每个元素自成一个区间 for(int i=2;i<=n;i++){//由2开始遍历 ,因为第一个元素符号永远不变 if(sum>0&&a[i]==1){//如果此时总和大于0且该个数字为1,我们就把它与前一个数字合并 p[i-1]=1;//前面元素打上标签 sum-=2;//1转换为-1,则总和减去2 i++;//如果从i-1开始合并的话则i+1个数字无论是否合并前一个区间符号都不变, //并且如果i-1作为区间的开始则i就不能成为区间的开始,所所以i+1的符号是一定不会变的 } else if(sum<0&&a[i]==-1){//同上 p[i-1]=1; sum+=2; i++; } } if(sum!=0){//如果遍历完后总和还不为0的话就说明不存在合法方案 cout<<-1<<endl; continue; } int l,r,num=0; for(int i=1;i<=n;i++){ l=i;//初始一个元素为一个区间 r=i; if(p[i]){//如果该元素被打上标记了说明和后面一个元素是同属于一个区间 while(i<=n&&p[i]) r=i+1,i+=2; i--; } res[num++]={l,r}; } cout<<num<<endl; for(int i=0;i<num;i++) cout<<res[i].l<<" "<<res[i].r<<endl; } } /* 我们一开始把所有元素都划分为一个区间,区间只含有一个元素 然后我们发现,当我们想要合并两个区间时,例如 -1 1 1 1 1 我们如果从-1开始出发,只有第二个1和第四个1在合并的时候需要改变符号,而其余的数字无论是合并还是不合并都为相加 因此我们只需要知道由谁开始就可以得到哪些符号是要变化的 */