装饰大楼 NOIP2015模拟11.3

上升子序列问题

其实和这东西只是扯上边而已,完全没有考算法…………..

———————————–切入正题————————-

题目:

际信息学奥林匹克竞赛将要在日本召开了。为了欢迎全世界的选手们,委员会决定将从机场到宿舍沿路的大楼装饰起来。根据某著名设计师的设计,做装饰的大楼从机场到宿舍的方向必须高度严格递增。也就是说,如果做装饰的大楼从机场开始高度顺次为hi,那么必须满足hi是递增的。
为了使尽量多的装饰品发挥光泽,做装饰的大楼希望越多越好。担任挑选被装饰的大楼的工作的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君有可能并没有漏写一个数而是出现了其他的书写事故,因此无解也是有可能的。

————————–分割———————-

输入

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

样例输入:4 1 1 2

输出

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

样例输出:5

——————刨解题目———————-

给你一个缺了一个数的上升子序列,求还原后的序列的个数。

——————-分割————————-

1.有解情况
插入位置前方已经取遍了1~k,该位置便可以取1~k+1,加入答案即可。当然要注意判重。

2.无解情况:有两种。
第一种便是序列中某一位置的数比前面序列里最大的数大了2以上,即a[i]-max(a[1~i-1])>2。
第二种便是序列中某一位置的数比前面序列里的数大了2,且这种情况出现的两次或以上。

3.判重:一般方法会炸,优化的方法有很多,自己想想就可以了。

———分割———
附代码(free pascal版本)

var
        a:array[0..1000005]of longint;
        maxn:array[0..1000005,1..2]of longint;
        bz:boolean;
        i,k,maxm,x,y,n:longint;
        ans:int64;
begin
        assign(input,'building.in'); reset(input);
        assign(output,'building.out'); rewrite(output);
        readln(n);
        for i:=1 to n-1 do
        begin
                readln(a[i]);
                if a[i]-maxn[i-1,1]>2 then
                begin
                        writeln(0);
                        close(input); close(output);
                        halt;
                end;
                if a[i]-maxn[i-1,1]=2 then
                begin
                        if bz then
                        begin
                                writeln(0);
                                close(input); close(output);
                                halt;
                        end;
                        bz:=true;
                        x:=i;
                end;
                if a[i]>maxn[i-1,1] then
                begin
                        maxn[i,1]:=a[i];
                        maxn[i,2]:=i;
                end
                else maxn[i]:=maxn[i-1];
        end;
        a[n]:=maxlongint div 2;
        if bz then
        begin
                writeln(x-maxn[x-1,2]);
                close(input); close(output);
                halt;
        end;
        for i:=1 to n do
        begin
                if a[i]-maxn[i-1,1]=2 then ans:=ans+i-maxn[i-1,2]
                else
                begin
                        ans:=maxn[i-1,1]+1+ans;
                        if maxn[i-1,1]+1>=a[i] then dec(ans);
                end;
        end;
        writeln(ans);
        close(input); close(output);
end.

就这样吧。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值