您的位置:首页 > 其它

【NOIP2015模拟11.3】装饰大楼

2016-04-18 20:17 260 查看

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君有可能并没有漏写一个数而是出现了其他的书写事故,因此无解也是有可能的。

solution

显然题目的b数组就是一个以i结尾最长上升子序列的最长长度,题目要求添上一个依旧合法,

因为是最长上升子序列,所以b数组一定由前面的某一个+1转移过来,如没有一个数+1转移出当前的数,那么插入的那个数一定要在当前的前面并且值一定为b[i]-1

如果没有上述情况,则每个位置都有max(b[1~i])+1种方案-重复,

我们发现,重复的情况只存在当我当前的最高可插入高度>=下一高度时,就会有一种重复的情况出现,减去即可,

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int N=1000500,maxlongint=2147483640;
int read(int &n)
{
char ch=getchar();
while((ch!='-')&&((ch<'0')||(ch>'9')))ch=getchar();
int q=0,w=1;if(ch=='-')w=-1,ch=getchar();
while(ch>='0' && ch<='9')q=q*10+ch-48,ch=getchar();n=q*w;return n;
}
int n;
LL ans;
int a
;
bool z
;
int main()
{
freopen("building.in","r",stdin);
freopen("building.out","w",stdout);
int q,w;z[0]=1;
read(n);
q=n;
fo(i,1,n-1)
{
read(a[i]);
if(!a[i]){printf("0\n");return 0;}
if(!z[a[i]-1])
{
if(q!=n && a[q]!=a[i] || a[i]>1&&!z[a[i]-2]){printf("0\n");return 0;}
q=min(i,q);
}
z[a[i]]=1;
}
ans=0;
if(q<n)
{
w=a[q]-1;
fo(i,0,q)if(a[i]+1==w){ans=q-i;break;}
}
else
{
a
=maxlongint,q=0;
fo(i,1,n-1)
q=max(q,a[i]),ans+=(LL)(q)+1-(q+1>=a[i+1]);
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: