首页 > 其他分享 >【XSY2271】青蛙(栈)

【XSY2271】青蛙(栈)

时间:2022-10-30 10:24:13浏览次数:25  
标签:输出 10 样例 青蛙 石头 编号 XSY2271

题面

Description

从前有 \(n\) 块石头排成一排,编号从\(1\)到\(n\)。有 \(n\) 只青蛙站在这 \(n\) 块石头上,其中编号为 \(i\) 的青蛙站在编号 \(i\) 的石头上。

这 \(n\) 只青蛙有一个秘密计划,在某个风和日丽的早上,它们同时起跳,编号为 \(i\) 的青蛙跳到编号为 \(p_i\) 的石头上。跳跃之后,每个石头上仍然有且仅有一只青蛙。即: \(p_i\) 为一个 \(1\) 到 \(n\) 的全排列。

天上有颗卫星,可以监控青蛙的跳动。由于一些技术原因,卫星只能提供有限的信息:对于 \((i,i+1)\) 区间(其中 \(1≤i<n\)),有多少只青蛙经过此区间。例如:一只青蛙从编号为\(4\)的石头跳到编号为\(1\)的石头,它将依次经过 \((3,4)\), \((2,3)\), \((1,2)\) 共三个区间。

我们想根据卫星提供的信息还原出每只青蛙跳到哪块石头上(即 \(p_i\) )。

Input

第一行一个整数 \(n\) ,表示青蛙数量 \((2≤n≤2×10^5)\)

第二行包含 \(n−1\) 个整数 \(a_1,a_2,⋯a_{n−1}(0≤a_i≤2×10^5)\) ,其中 \(a_i\) 表示有多少只青蛙经过 \((i,i+1)\) 区间。

Output

如果不存在跳跃方案,输出No

否则在第一行输出Yes,第二行输出 \(n\) 个整数 \(p_1,p_2,⋯,p_n\) 。如果有多组解,输出任意一种。

Sample Input & Sample Output

【样例输入1】

5
2 4 2 2

【样例输出1】

Yes
4 3 2 5 1

【样例输入2】

4
1 2 3

【样例输出2】

No

HINT

【数据范围与约定】

子任务1(\(10\)分): \(1≤n≤10\)

子任务2(\(40\)分): \(1≤n≤2000\)

子任务3(\(50\)分): \(1≤n≤2×10^5\)

题解

首先注意到一个性质:每一个\(a[i]\)都得是偶数(如果左边跳一只青蛙到右边,则右边必定有一只青蛙跳到左边,这样会使\(a[i]\)加两次)。

然后,我们考虑相邻的两个\(a\):\(a[i-1]\)与\(a[i]\)。

它们只能有这三种关系:

  1. \(a[i-1]=a[i]\)

  2. \(a[i-1]+2=a[i]\)

  3. \(a[i-1]-2=a[i]\)

来逐一解释一下:

  1. \(a[i-1]=a[i]\)

    这说明青蛙越过这两个区间的合法情况是这样的:

    (其中的红线代表青蛙跳跃的路线)

    在这里插入图片描述

    即如果有青蛙经过区间\((i-1,i)\),它必定要经过\((i,i+1)\),否则\(a[i-1]\neq a[i]\)。而由于题目要求输出任意一种方案,我们不妨令青蛙\(i\)跳到了原地。

  2. \(a[i-1]+2=a[i]\)

    还是画个图先:

    在这里插入图片描述

    意思就是,该经过的还是两个都得经过,不过\(i\)要往右跳,另一个人要从右边跳到\(i\),这样才能使得\(a[i]=a[i-1]+2\)。而由于题目要求输出任意一种方案,我们不妨设\(i\)与右边的某只青蛙互换了位置。然后我们将\(i\)插入一个栈里面。

  3. \(a[i-1]-2=a[i]\)

    图:

    在这里插入图片描述

    意思就是,该经过的还是两个都得经过,不过\(i\)要往左跳,另一个人要从左边跳到\(i\),这样才能使得\(a[i]=a[i-1]-2\)。而由于题目要求输出任意一种方案,我们不妨设\(i\)与左边的某只青蛙互换了位置。所以我们取栈顶的元素,这个元素\(x\)代表着\(x\)要与\(x\)右边的某个元素交换位置,而由于我们是从小到大循环遍历\(i\)的,所以第\(i\)只青蛙刚好符合条件。所以\(x\)与\(i\)互换位置(\(p[i]=x,p[x]=i\))。

最后把\(p[i]\)输出了就好了。

代码如下:

#include<bits/stdc++.h>

#define N 200010

using namespace std;

int n,a[N],p[N],st[N],top;

void NO()
{
	puts("No");
	exit(0);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		if(a[i]==a[i-1])//自己跳自己
			p[i]=i;
		else if(a[i]==a[i-1]+2)//i往右跳 
			st[++top]=i;
		else if(a[i]==a[i-1]-2)//i往左跳
		{
			if(!top)//i往左跳,如果左边没人跳过来,就说明i跳不过去 
				NO();
			p[st[top]]=i;
			p[i]=st[top--];
		}
		else
			NO();//因为每一个a[i]得是偶数且与相邻两个的相差不超过2,其他情况不符合 
	}
	if(top)//栈里还有青蛙要往右跳,说明不合法 
		NO();
	puts("Yes");
	for(int i=1;i<=n;i++)
		printf("%d ",p[i]);
	return 0;
}

标签:输出,10,样例,青蛙,石头,编号,XSY2271
From: https://www.cnblogs.com/ez-lcw/p/16840591.html

相关文章

  • 【poj1061】青蛙的约会(扩展欧几里得)
    不妨设青蛙A的出发点坐标是\(m1\),青蛙B的出发点坐标是\(n1\)。青蛙A一次能跳\(m\)米,青蛙B一次能跳\(n\)米,跳一圈长\(l\)米,设青蛙A、B跳了\(x\)次。那么题目要求的是满足下......
  • 有一天,青蛙先生看到路上有只破鞋子。3
    有一天,青蛙先生看到路上有只破鞋子。http://ds.163.com/article/63387619880c710001954ef5/?2022/10/06_=2022/10/05http://ds.163.com/feed/63387619880c710001954ef5/?202......
  • 剑指 Offer 10- II. 青蛙跳台阶问题
    一、题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n 级的台阶总共有多少种跳法。答案需要取模1e9+7(1000000007),如计算初始结果为:100000000......
  • 青蛙跳台阶
    1.普通跳台阶题目地址(70.爬楼梯)https://leetcode.cn/problems/climbing-stairs/题目描述假设你正在爬楼梯。需要n 阶你才能到达楼顶。每次你可以爬1或2个......