日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

UVA 10534 - Wavio Sequence

發(fā)布時(shí)間:2025/4/14 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UVA 10534 - Wavio Sequence 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這道題的意思是讓我們求一個(gè)上升子序列  + 一個(gè)下降字序列,且兩邊的長度是相等的,由于用正常的 O(n2) 算法會(huì) TLE ,所以這里我們采用二分法求最長上升子序列,這里需要利用兩個(gè)棧來儲(chǔ)存“相當(dāng)于”最長上升子序列的串(我利用一個(gè)棧通過再次初始化棧頂top來第二次使用),在此同時(shí)開兩個(gè)數(shù)組f1[i],f2[i],分別表示前i個(gè)元素的最長字串長度,最后比較同一個(gè)位置時(shí)(注意f1,f2一個(gè)正一個(gè)反)兩個(gè)數(shù)組值的大小,取小的一個(gè)(因?yàn)橐髢蛇呴L度相等)賦值給新開的數(shù)組flag[](我用num不斷刷新),最后遍歷數(shù)組,找出其最大的就可以了。

這里說一下二分法求最長上升子序列:復(fù)雜度為O(n×logn):

它是通過一個(gè)棧來實(shí)現(xiàn)的,我們遍歷一個(gè)母串,如果當(dāng)前值大于棧頂元素的值,我們將其壓入棧,而當(dāng)前位置 i 的最長上升子序列的長度就是棧頂指針的值(或+1),如果當(dāng)前值等于棧頂元素的值,不壓入棧,同樣當(dāng)前位置 i 的最長上升子序列的值就是棧頂指針的值(或+1),如果當(dāng)前值小于棧頂元素的值,不壓入棧,但是我們要用二分法找出恰好不小于當(dāng)前值的那個(gè)位置,這個(gè)位置我們這里定義為x,并將x位置的值替換為當(dāng)前值,而當(dāng)前位置 i 的最長上升子序列的長度就是x這個(gè)指針的值(或+1);

為什么這樣是成立的呢:別人的證明:

實(shí)際上就是運(yùn)用了貪心的思想,每次進(jìn)行替換操作后增強(qiáng)了后續(xù)最長上升子序列的“長度增長的潛力”,后續(xù)得到的解一定不會(huì)比不替換更優(yōu)。

? ? 簡(jiǎn)單證明一下其正確性。我們用a[i]替換掉了S[mid],對(duì)后續(xù)某一元素a[j]來講,可能會(huì)認(rèn)為此時(shí)a[j]前的元素標(biāo)號(hào)并不是嚴(yán)格升序了,這會(huì)不會(huì)有問題呢?實(shí)際是不會(huì)有問題的。我們不妨設(shè)a[j]左邊的元素依次為A1、A2、……,這樣A1我們必然可以不動(dòng),因?yàn)榇饲癆1已經(jīng)更新至最新了,標(biāo)號(hào)必然是所有曾在這個(gè)位置的元素中的標(biāo)號(hào)最大的一個(gè),那么對(duì)于A2呢,我們不妨想想現(xiàn)在的A1剛進(jìn)入這個(gè)棧的時(shí)候吧,那個(gè)時(shí)候的A2必然也在那個(gè)時(shí)候之前更新到當(dāng)時(shí)的最新了吧,并且A1左邊的元素的個(gè)數(shù)從那個(gè)時(shí)刻起也沒有變過吧?現(xiàn)在這個(gè)問題就可以不斷遞歸下去了,我們按這種方式一定可以找到一個(gè)序號(hào)嚴(yán)格遞增的序列,即使這個(gè)序列并不是在a[j]入棧時(shí)我們所看到的序列,但這又有什么關(guān)系呢,反正結(jié)果對(duì)就是了。

? ? 再簡(jiǎn)單說明一下其最優(yōu)性。既然前面已經(jīng)證明了其正確性,那么按前面的方法至少可以得到一個(gè)長度可觀的最長上升子序列,但究竟其是否是最長的呢?按上面算法的思路,如果想要得到的長度更長的話,那么只有一個(gè)措施,就是將原來的替換操作變成插入操作,要不然是沒辦法增加長度的。然而如果將替換操作變成插入操作,我們還能保證一定可以得到一個(gè)標(biāo)號(hào)嚴(yán)格升序的上升子序列嗎?顯然不能。比如一次插入操作在S[k]和S[k+1]之間,我們插入了一個(gè)a[i],但是如果此時(shí)有a[j]>S[k+1],那么a[j]的左邊是沒辦法構(gòu)造出一個(gè)長度為k+2的標(biāo)號(hào)嚴(yán)格升序的上升子序列的。既然第一次插入操作都會(huì)有錯(cuò),那肯定就不用考慮后續(xù)再有插入操作了。

代碼如下:

#include<stdio.h>
#define MAXN 10010
int a[MAXN], f[MAXN], f1[MAXN], f2[MAXN];
int n,num;
int up_bd(int *f, int t, int v)
{
int m;
int first = 0;
while(first < t)
{
m = first + (t - first)/2;
if(f[m] < v) first = m + 1;
else t = m;
}
f[first] = v;
return first;
}
void solve()
{
int top;
top = 0;
f[0] = a[0];
f1[0] = 1;
int x,y;
for(int i = 1; i < n; i ++)
{
if(a[i] > f[top]) {f[++top] = a[i];x = top + 1;}
else if(a[i] == f[top]) {f[top] = a[i];x = top + 1;}
else if(a[i] < f[top]) x = up_bd(f,top,a[i])+1;
f1[i] = x;
}
top = 0;
f[0] = a[n-1];
f2[0] = 1;
for(int i = n-2; i >= 0; i --)
{
if(a[i] > f[top]) {f[++top] = a[i];y = top + 1;}
else if(a[i] == f[top]) {f[top] = a[i];y = top + 1;}
else if(a[i] < f[top]) y = up_bd(f,top,a[i])+1;
f2[n-1-i] = y;
}
num = 0;
int min = 0;
for(int i = 0; i < n; i ++)
{
if(f1[i] > f2[n-i-1]) min = f2[n-i-1];
else min = f1[i];
if(min > num) num = min;
}
printf("%d\n",2*num - 1);
}
void input()
{
while(scanf("%d",&n) == 1)
{
for(int i = 0; i < n; i ++)
scanf("%d",&a[i]);
solve();
}
}
int main()
{
input();
return 0;
}




轉(zhuǎn)載于:https://www.cnblogs.com/yuzhaoxin/archive/2012/03/31/2427740.html

總結(jié)

以上是生活随笔為你收集整理的UVA 10534 - Wavio Sequence的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。