難解的問題(vijos1369)

2021-05-28 16:11:42 字數 1712 閱讀 8651

演算法: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。但是,現在還有乙個附加條件 求出...

克服困難,解決遇到的問題!!

遇到了一些問題,一度產生放棄的想法,不過好歹最後還是一路堅持了下來,將問題解決了大半 反觀以前做圓角邊框的時候,要用程式解大量的曲線方程,算得我真是想吐,也是想放棄,不過還是挺到最後把這塊骨頭啃了下來 這次做的是乙個將所有形狀放縮成同一高度的功能,遇到的一些困難,都是因為粗心大意所致,不過也是有一些...