演算法:dp
分析:非常經典的乙個題,個人認為cai神牛的解法非常獨特,值得借鑑!
簡單的說,題目就是求乙個包含某一項的最長上公升序列,設序列的序號是m,我們可以採用這種思路:先求1~m中以m為終點的最長上公升,再求m~n中以m為起點的最長上公升,兩項累加一下就可以得出結果。
題目資料量很大,因此我們只能採用基於二分的最長不x來解決問題。
program vijos1369;
const
maxn=300000;
var n,m,tot,ans:longint;
a,f:array [0..maxn] of longint;
procedure init;
var i:longint;
begin
ans:=0;
readln(n,m);
for i:=1 to n do read(a[i]);
for i:=1 to m-1 do if a[i]=a[m] then a[i]:=maxlongint;
end;
procedure insert(l,r,x:longint);
var mid:longint;
begin
mid:=(l+r) shr 1;
while (l<=r) and (not ((f[mid]<=x) and (f[mid+1]>=x))) do
begin
if xf[mid] then l:=mid+1;
mid:=(l+r) shr 1;
end;
if l>r then
begin
if f[1]<>a[m] then f[1]:=x;
endelse if (f[mid+1]<>a[m]) and (f[mid]<>x) then f[mid+1]:=x;
end;
procedure solve(l,r:longint);
var i:longint;
begin
fillchar(f,sizeof(f),maxlongint);
f[1]:=a[l];
tot:=1;
for i:=l+1 to r do
begin
if a[i]>f[tot] then
begin
inc(tot);
f[tot]:=a[i];
endelse insert(1,tot-1,a[i]);
end;
if (l=1) and (r=m) then
begin
for i:=1 to tot do
begin
inc(ans);
if f[i]=a[m] then break;
end;
endelse inc(ans,tot);
end;
begin
assign(input,'vj1369.in'); reset(input);
assign(output,'vj1369.out'); rewrite(output);
init;
solve(1,m);
solve(m,n);
if n=1 then writeln(1) else writeln(ans-1);
close(input); close(output);
end.
Vijos P1369 難解的問題
題目大意 給你乙個序列,叫你求最長上公升子串行長度,但必須包含第k項。解題思路 我們把k左邊的比a k 大的數去掉,k右邊的比k小的數去掉,就可以保證選到a k 了 因為左邊的數小於a k 而a k 小於右邊的數,取了a k 一定比不取優 此題由於n到300000,需要優化後的lis,我使用了單調佇...
vijos 難解的問題
描述 在你的幫助下,蔚藍來到了埃及.在金字塔裡,蔚藍看到了乙個問題,傳說,能回答出這個問題的人就能受到埃及法老的祝福,可是蔚藍日夜奮戰,還是想不出來,你能幫幫他麼?胡扯,教主怎麼可能想不出來 ws這人說的 問題是這樣的 給定乙個序列.求最長上公升子串行 lis p1。但是,現在還有乙個附加條件 求出...
克服困難,解決遇到的問題!!
遇到了一些問題,一度產生放棄的想法,不過好歹最後還是一路堅持了下來,將問題解決了大半 反觀以前做圓角邊框的時候,要用程式解大量的曲線方程,算得我真是想吐,也是想放棄,不過還是挺到最後把這塊骨頭啃了下來 這次做的是乙個將所有形狀放縮成同一高度的功能,遇到的一些困難,都是因為粗心大意所致,不過也是有一些...