C. Polycarp Restores Permutation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
An array of integers p1,p2,…,pn
is called a permutation if it contains each number from 1 to n exactly once. For example, the following arrays are permutations: [3,1,2], [1], [1,2,3,4,5] and [4,3,1,2]. The following arrays are not permutations: [2], [1,1], [2,3,4]
.
Polycarp invented a really cool permutation p1,p2,…,pn
of length n. It is very disappointing, but he forgot this permutation. He only remembers the array q1,q2,…,qn−1 of length n−1, where qi=pi+1−pi
.
Given n
and q=q1,q2,…,qn−1
, help Polycarp restore the invented permutation.
Input
The first line contains the integer n
(2≤n≤2⋅105) — the length of the permutation to restore. The second line contains n−1 integers q1,q2,…,qn−1 (−n<qi<n
).
Output
Print the integer -1 if there is no such permutation of length n
which corresponds to the given array q. Otherwise, if it exists, print p1,p2,…,pn
. Print any such permutation if there are many of them.
Examples
Input
Copy
3
-2 1
Output
Copy
3 1 2
Input
Copy
5
1 1 1 1
Output
Copy
1 2 3 4 5
Input
Copy
4
-1 2 2
Output
Copy
-1
题意:有n个数,后面给出了n-1个数字,表示的是第n+1个数-第n个数的值
然后叫我们输出这n个数,这n个数是由前n组合成的,每个数都是不同的而且必须从1开始,不能跳过一些数比如1 2 4 5是不行的,因为少了3,1 1也是不行的因为重复了,0 2 4也是不行的因为最小是从1开始
思路:我们可以设第一个数为x,然后可以推出后面的数和第一个数的关系
比如第一个样例num[1]=x num[2]=x-2 num[3]=x-1
这三个数的和 == 3x-3 也就等于从1到3和,也就是前N项和
然后我们解方程n*(n+1)/2 = 3x-3 可以算出第一个数x,这样我们就可以推出之后的数。推出第一个数之后我们还要判断有没有找对,比如第三组样例
10 = 4x+2 得出x==2 但这是错的,原因这样算出来数列是 2 0 3 6
所以我们之后还要判断找出x后的数列是不是符合的,这个bool数组就可以了
坑点:范围,绝对不能用int 不能用int 不能用int !!!要用long long (我什么都不知道5555555555)还有一个坑点代码说了
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2e5+10;
long long int num[maxn],sum[maxn]; //不要忘了
int main()
{
long long int n,m,k; //long long
long long int ans;
cin>>n;
m=0;k=0;
memset(num,0,sizeof(num));
for (int i=1;i<n;i++)
{
scanf("%lld",&num[i]);
num[i]=num[i-1]+num[i];
m=m+num[i];
}
if (n%2==0) ans=(n/2)*(n+1); //看一下n的范围就知道这里要注意
else ans=((n+1)/2)*n;
// cout<<ans<<endl;
if ((ans-m)%n==0) k=(ans-m)/n;
else k=-1;
// cout<<k<<endl;
for (int i=0;i<n;i++)
{
if (k+num[i]<=0||k+num[i]>maxn-10) //这里是找有没有重复和缺少的
break; //注意范围,大于n最大也是不需要考虑的,因为数列最大不能超过n
sum[k+num[i]]=1;
// cout<<k+num[i]<<"--"<<k<<endl;
}
sort(sum+1,sum+n+1); //数组有0说明有缺少
if (sum[1]==0)
k=-1;
if (k<=0) cout<<-1;
else
for (int i=0;i<n;i++)
if (i==0) cout<<k;
else cout<<" "<<k+num[i];
cout<<endl;
return 0;
}
略坑略坑
恢复排列数组的算法思路与实现

博客围绕恢复排列数组问题展开,给定长度为n的排列数组的n - 1个差值,需恢复原排列。介绍了设首项为x推导后续项与首项关系,通过前N项和解方程求首项的思路,还提及判断结果是否符合要求,强调注意范围要用long long。
524

被折叠的 条评论
为什么被折叠?



