纪中暑假集训 2020.07.30【NOIP提高组】模拟 T1:【NOIP2015模拟11.3】装饰大楼

【NOIP2015模拟11.3】装饰大楼

Description

国际信息学奥林匹克竞赛将要在日本召开了。为了欢迎全世界的选手们,委员会决定将从机场到宿舍沿路的大楼装饰起来。根据某著名设计师的设计,做装饰的大楼从机场到宿舍的方向必须高度严格递增。也就是说,如果做装饰的大楼从机场开始高度顺次为h1,h2,h3,…,那么必须满足h1<h2<h3<…。
为了使尽量多的装饰品发挥光泽,做装饰的大楼希望越多越好。担任挑选被装饰的大楼的工作的JOI君,考虑到了大楼的主人可能会有“希望自己的大楼被装饰起来,而且,为了让大楼很显眼,希望这栋大楼是所有装饰起来的大楼中离宿舍最近的一栋”这种无理要求。
从机场到宿舍沿路共有N栋大楼,从机场开始的第i栋大楼称作大楼i,N栋大楼的高度彼此不同。JOI君为了满足各种各样的要求,决定事先计算出“如果装饰大楼i,并且让大楼i是所有装饰起来的大楼中离宿舍最近的一栋,那么选出的大楼最多有Ai个”这样的东西。JOI君计算出了整数列A1,A2,…,AN,然后发给了日本信息学奥林匹克竞赛委员会的K理事长。
然而,K理事长收到的信息只有一个长度为N-1的整数列B1,B2,…,B[N-1]。K理事长不知道大楼高度的情报,因此没有办法计算出Ai。
K理事长认为,JOI君一定是漏写了一个数。考虑到以A1,A2,…,AN为A数组的大楼的高度大小关系可能有很多种,K理事长想知道,删掉一个数后能得到B1,B2,…,B[N-1]的合法的A数组一共有多少种?
然而实际上,JOI君有可能并没有漏写一个数而是出现了其他的书写事故,因此无解也是有可能的。

Input

第一行一个正整数N,表示从机场到宿舍沿路的大楼数量。
接下来N-1行,第i行(1<=i<=N-1)为Bi,表示K理事长收到的第i个数的值。

Output

输出一行一个正整数,表示可能的A数组的数量

Sample Input

4
1
1
2

Sample Output

5

【HINT】

合法的A数组共有以下5种:
1,2,1,2,此时的高度序列为2413或3412
1,1,2,3,此时的高度序列为2134
1,1,2,1,此时的高度序列为3241
1,1,2,2,此时的高度序列为2143
1,1,1,2,此时的高度序列为3214

Data Constraint

对于10%的数据,N<=8
对于40%的数据,N<=300
对于100%的数据:
2<=N<=10^6
1<=Bi<=N (1<=i<=N-1)

反思&题解

比赛思路: 一脸懵……but看到有可能有无解的情况,果断输出0,高兴地骗了14分 (日本人出的题果然斯国一!!!)
正解思路: 很显然a数组的每个位置是求一次最长上升子序列,由此可得 b [ i ] b[i] 的取值范围为 [ 1 , n 1 ] [1,n-1]
之后我们考虑不合法的情况 (也就是输出0可以骗分的情况)
1. 相邻两个数的差值超过2,很明显怎么补进去一个数都不行
2. 有2对及以上差值等于2,1个数字只能补1个位置,所以不合法
最后把他们补进去就行了,不过记得要判一下重
反思: 数学思想要多练一练,刺激一下

CODE

#include<bits/stdc++.h>
using namespace std;
long long b[1000005],n,ans,num,mx;
int main()
{
	freopen("building.in","r",stdin);
	freopen("building.out","w",stdout);
	scanf("%lld",&n);
	int i,w,tot;
	for (i=1;i<n;i++)
	{
		scanf("%lld",&b[i]);
		mx=max(mx,b[i-1]);
		if (b[i]>mx+2)
		{
			printf("0\n");
			return 0;
		}
		if (b[i]==mx+2)
		{
			num++;
			if (num==2)
			{
				printf("0\n");
				return 0;
			}
			tot=mx+1;
			w=i-1;
		}
	}
	if (num)
	{
		mx=0;
		for (i=1;i<=w;i++)
		{
			mx=max(mx,b[i]);
			if (mx+1>=tot) ans++;
		}
		if (tot==1) ans++;
		printf("%lld\n",ans);
	}
	else
	{
		mx=0;
		for (i=1;i<n;i++)
		{
			mx=max(mx,b[i]);
			ans+=mx+1;
			if (i!=n-1 && mx+1>=b[i+1]) ans--;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CMC_YXY/article/details/107700516