Blog 2.递推与矛盾问题。

1.递推这个嘛,先来个简单的
可是我还是写错了啊啊啊,超时
Codeforces上的题
C. Polycarp Restores Permutation
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
An array of integers p1,p2,…,pnp1,p2,…,pn is called a permutation if it contains each number from 11 to nn exactly once. For example, the following arrays are permutations: [3,1,2][3,1,2], [1][1], [1,2,3,4,5][1,2,3,4,5] and [4,3,1,2][4,3,1,2]. The following arrays are not permutations: [2][2], [1,1][1,1], [2,3,4][2,3,4].

Polycarp invented a really cool permutation p1,p2,…,pnp1,p2,…,pn of length nn. It is very disappointing, but he forgot this permutation. He only remembers the array q1,q2,…,qn−1q1,q2,…,qn−1 of length n−1n−1, where qi=pi+1−piqi=pi+1−pi.

Given nn and q=q1,q2,…,qn−1q=q1,q2,…,qn−1, help Polycarp restore the invented permutation.

Input
The first line contains the integer nn (2≤n≤2⋅1052≤n≤2⋅105) — the length of the permutation to restore. The second line contains n−1n−1 integers q1,q2,…,qn−1q1,q2,…,qn−1 (−n<qi<n−n<qi<n).

Output
Print the integer -1 if there is no such permutation of length nn which corresponds to the given array qq. Otherwise, if it exists, print p1,p2,…,pnp1,p2,…,pn. Print any such permutation if there are many of them.

Examples
inputCopy
3
-2 1
outputCopy
3 1 2
inputCopy
5
1 1 1 1
outputCopy
1 2 3 4 5
inputCopy
4
-1 2 2
outputCopy
-1
题意:
一个数组,大小n,里面是n的一个排列数,20000+的n
给你相邻的n-1对数组元素的差
让你搞出来这个排列数数组;

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[1000001];
int vis[1000001];
int p[1000001];

int main()
{
	int j;
	int n;
	//5 1111 12345     1
	bool flag=0;
	cin>>n;
	for(int i=1;i<=n-1;i++)
	cin>>a[i];
	if(n+a[1]<=0)
	{
	cout<<"-1";
	return 0;	
	}
	int start=a[1]>0?1:-a[1];
	int end=a[1]>0?n-a[1]:n;
	for(int k=start;k<=end;k++)
	{
	memset(vis,0,sizeof(vis));
	p[1]=k;
	vis[k]=1;
	if(p[1]+a[1]<=0)
	continue;
	if(p[1]+a[1]>n)
	continue;
	for(j=2;j<=n;j++)
	{
	p[j]=p[j-1]+a[j-1];
	if(p[j]<=0)
	break;
	if(p[j]>n)
	break;
	if(vis[p[j]])
	break;	
	vis[p[j]]=1;
	}
	if(j==n+1)
	{
		flag=1;
		break;
	} 
	}
	if(flag)
	for(int i=1;i<=n;i++)
	cout<<p[i]<<" ";
	else
	cout<<"-1";
	return 0;
}

先看我的笨蛋超时思路,唉优化了好长时间
真是傻到一种境界,看看大佬的
唉差距啊

这个数组中最大数4减去4,为0
后只需判断
{p[i]-0}这个数组是否符合要求
Why?
其实是这个样子滴
假设第一个数就是1,后来就算出来喽这些值
这些值由于第一开始有可能不是1,所以一定会与正确的值相差一段距离;
后面的值也有可能为负值,但由于是排列各个不同,且相差的值应当是一样的;
故只需算出这个差了多少值就可以啦
那么这个相差的值是多少呢
很简单啊,
就是这些数中最大的值与n相差
或者最小的值(可能是负数喽)与1相差
后面平定相差值
过程中判断是否vis或越界就可以啦

#include <bits/stdc++.h>
using namespace std;

int main() {
	int n, temp;
	cin >> n;
	vector<int> p(n);//设置一个动态内存大小为n的vector
	p[0] = 1;//将第一个数赋值为1
	for(int i = 1; i < n; ++i) {
		cin >> temp;//输入差
		p[i] = p[i-1] + temp;求出后面一个
	}
	//这个显然算出来的是假设用第一个为1的数组
	int disp = *max_element(p.begin(), p.end()) - n;//这个数组中最大的数减去n
	int done[n] = {0};
	for(int i = 0; i < n; ++i){
		p[i] -= disp;
		if(p[i] < 1 || p[i] > n || done[p[i] - 1]) {
			cout << "-1\n";
			return 0;
		}
		done[p[i] - 1] = 1;
	}
	for(auto x: p)
		cout << x << " ";
	cout << "\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值