上升子序列问题
其实和这东西只是扯上边而已,完全没有考算法…………..
———————————–切入正题————————-
题目:
际信息学奥林匹克竞赛将要在日本召开了。为了欢迎全世界的选手们,委员会决定将从机场到宿舍沿路的大楼装饰起来。根据某著名设计师的设计,做装饰的大楼从机场到宿舍的方向必须高度严格递增。也就是说,如果做装饰的大楼从机场开始高度顺次为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.
就这样吧。