题目描述
有一天,一个名叫顺旺基的程序员从石头里诞生了。又有一天,他学会了冒泡排序和独立集。在一个图里,独立集就是一个点集,满足任意两个点之间没有边。于是他就想把这两个东西结合在一起。众所周知,独立集是需要一个图的。那么顺旺基同学创造了一个算法,从冒泡排序中产生一个无向图。
这个算法不标准的伪代码如下:
procedure bubblesortgraph(n, a[]) :
/*输入:点数n,1到n的全排列a。
输出:一个点数为n的无向图G。*/
创建一个有n个点,0条边的无向图G。
repeat
swapped = false
for i 从 1 到 n-1 :
if a[i] > a[i + 1] :
在G中连接点a[i]和点a[i + 1]
交换a[i]和a[i + 1]
swapped = true
until not swapped
输出图G。
//结束。
那么我们要算出这个无向图G最大独立集的大小。但是事情不止于此。顺旺基同学有时候心情会不爽,这个时候他就会要求你再回答多一个问题:最大独立集可能不是唯一的,但有些点是一定要选的,问哪些点一定会在最大独立集里。今天恰好他不爽,被他问到的同学就求助于你了。
输入
两行。第一行为N,第二行为1到N的一个全排列。
输出
两行。第一行输出最大独立集的大小,第二行从小到大输出一定在最大独立集的点的编号(输入时的序号)。
样例输入
3
3 1 2
样例输出
2
2 3
提示
【数据范围】
30%的数据满足 N<=16
60%的数据满足 N<=1,000
100%的数据满足 N<=100,000
多列几个数据,就可以发现最大独立集大小,就是最长不下降子序列大小。难点就是求一定在最长不下降子序列的元素。我们从1到n求一遍最长不下降子序列,从n到1做一遍最长不下降子序列。每次记录位置,如果两次位置相加为答案且这一位置只有这一个数,那么它就是。
var
n,i,l,r,mid,len,m,num,j,v,tot,ii,ans:longint;
a,d,b,dp,dp2,sum:array[0..200011] of longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
begin
readln(n);
for i:=1 to n do
read(a[i]);
for i:=1 to n do
begin
l:=0;
r:=len;
while l<>r do
begin
mid:=(l+r+1) div 2;
if d[mid]<a[i] then l:=mid
else r:=mid-1;
end;
l:=l+1;
len:=max(len,l);
d[l]:=a[i];
dp[i]:=l;
end;
writeln(len);
ans:=len;
d[0]:=maxlongint;
len:=0;
for i:=n downto 1 do
begin
l:=0;
r:=len;
while l<>r do
begin
mid:=(l+r+1) div 2;
if d[mid]>a[i] then l:=mid
else r:=mid-1;
end;
l:=l+1;
len:=max(len,l);
d[l]:=a[i];
dp2[i]:=dp[i]+l-1;
if dp2[i]=ans then sum[dp[i]]:=sum[dp[i]]+1;
end;
for i:=1 to n do
begin
if (dp2[i]=ans)and(sum[dp[i]]=1) then
begin
m:=m+1;
b[m]:=i;
end;
end;
for i:=1 to m do
if i<>m then write(b[i],' ') else write(b[i]);
end.