給定乙個序列,初始為空。現在我們將1到n的數字插入到序列中,每次將乙個數字插入到乙個特定的位置。每插入乙個數字,我們都想知道此時最長上公升子串行長度是多少?
第一行乙個整數n,表示我們要將1到n插入序列中,接下是n個數字,第k個數字xk,表示我們將k插入到位置xk(0<=xk<=k-1,1<=k<=n)
n行,第i行表示i插入xi位置後序列的最長上公升子串行的長度是多少。
30 0 2
112
提示x0等於0 ,我們將1插入到位置0得到序列
x1等於0 ,我們將1插入到位置0得到序列
x2等於2 ,我們將1插入到位置0得到序列
資料範圍
30%„的資料 n<=1000
100%的資料 n<=100000
analysis
因為數字是從小到大插入的,所以我們可以構造出最終序列,然後o(nlogn)求最長上公升子串行。
關鍵是構造出最終序列。
2b青年:我會平衡樹!(我連2b都不如
平衡樹模擬插入,求出最終序列,雖然可以過,但是**量和時間不盡人意。
下面來講一下文藝的做法吧...
我們發現,將整個序列反過來做,如果當前數插入的位置定了,將不會再受到影響。
而這樣子就可以用樹狀陣列維護,首先將所有的位置都設為一,每次插入乙個數,相當於找到最前面的一段區間,它們的和=當前數插入的位置(設為l[1,i]),則這個插入的數的位置就是i。插入之後,將i這個位置置為零(用過了)。
可以通過二分來找到這個i,更好的方法是通過二進位制(剛學)。
看下面的**:
這是用樹狀陣列的定義來加速處理的方法,i從20開始取是因為資料範圍<=100000(理解不了可以看一下樹狀陣列的定義)。function get(k:longint):longint;
var ans,cnt,i:longint;
begin
ans:=0; cnt:=0;
for i:=20 downto 0 do begin
ans:=ans+1 shl i;
if (ans>=n) or (cnt+c[ans]>=k) then ans:=ans-1 shl i
else cnt:=cnt+c[ans];
end;
exit(ans+1);
end;
接下來我們就可以還可以再用樹狀陣列維護乙個區間最大值,當然直接套o(nlogn)的最長上公升子串行的傳統做法也可以,不過樹狀陣列比較方便。
上**:(沒看懂
var
i,j,k,n,tmp:longint;
c,cnt,pos,ans,fa:array[0..100000] of longint;
function getfa(t:longint):longint;
begin
if fa[t]=t then exit(t);
fa[t]:=getfa(fa[t]);
getfa:=fa[t];
end;
function lowbit(x:longint):longint;
begin
exit(x and (-x));
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure change(x,delta:longint);
begin
while x0 do begin
getmax:=max(getmax,c[x]);
x:=x-lowbit(x);
end;
end;
function get(k:longint):longint;
var ans,cnt,i:longint;
begin
ans:=0; cnt:=0;
for i:=20 downto 0 do begin
ans:=ans+1 shl i;
if (ans>=n) or (cnt+c[ans]>=k) then ans:=ans-1 shl i
else cnt:=cnt+c[ans];
end;
exit(ans+1);
end;
begin
readln(n);
for i:=1 to n do begin read(pos[i]); inc(pos[i]); inc(c[i]); if i+lowbit(i)<=n then c[i+lowbit(i)]:=c[i+lowbit(i)]+c[i]; end;
for i:=n downto 1 do begin
j:=get(pos[i]);
cnt[i]:=j;
while j
dec(c[j]);
j:=j+lowbit(j);
end;
end;
for i:=1 to n do c[i]:=0;
for i:=1 to n do begin
tmp:=getmax(cnt[i]-1)+1;
ans[i]:=max(ans[i-1],tmp);
change(cnt[i],tmp);
end;
for i:=1 to n do writeln(ans[i]);
end.
bzoj3173 最長上公升子串行
portal bzoj3173 solution 感覺自己需要智力 qwq 首先題目給的這個序列肯定是乙個 1 n 的排列,並且插入的順序是從小到大 仔細思考一下會發現如果知道了最終的序列,問題就比較好解決了,這裡提供一種用線段樹的做法 如果知道了最終的序列,記數字 i 在該序列中的位置為 loc ...
最長上公升子串行
問題描述 乙個數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2,an 我們可以得到一些上公升的子串行 ai1,ai2,aik 這裡1 i1 i2 ik n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等...
最長上公升子串行
最長上公升子串行問題是各類資訊學競賽中的常見題型,也常常用來做介紹動態規劃演算法的引例,筆者接下來將會對poj上出現過的這類題目做乙個總結,並介紹解決lis問題的兩個常用 演算法 n 2 和 nlogn 問題描述 給出乙個序列a1,a2,a3,a4,a5,a6,a7.an,求它的乙個子串行 設為s1...