日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

UVA 10534 - Wavio Sequence

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

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

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

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

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

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

? ? 簡(jiǎn)單證明一下其正確性。我們用a[i]替換掉了S[mid],對(duì)后續(xù)某一元素a[j]來(lái)講,可能會(huì)認(rèn)為此時(shí)a[j]前的元素標(biāo)號(hào)并不是嚴(yán)格升序了,這會(huì)不會(huì)有問(wèn)題呢?實(shí)際是不會(huì)有問(wèn)題的。我們不妨設(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í)刻起也沒(méi)有變過(guò)吧?現(xiàn)在這個(gè)問(wèn)題就可以不斷遞歸下去了,我們按這種方式一定可以找到一個(gè)序號(hào)嚴(yán)格遞增的序列,即使這個(gè)序列并不是在a[j]入棧時(shí)我們所看到的序列,但這又有什么關(guān)系呢,反正結(jié)果對(duì)就是了。

? ? 再簡(jiǎn)單說(shuō)明一下其最優(yōu)性。既然前面已經(jīng)證明了其正確性,那么按前面的方法至少可以得到一個(gè)長(zhǎng)度可觀的最長(zhǎng)上升子序列,但究竟其是否是最長(zhǎng)的呢?按上面算法的思路,如果想要得到的長(zhǎng)度更長(zhǎng)的話,那么只有一個(gè)措施,就是將原來(lái)的替換操作變成插入操作,要不然是沒(méi)辦法增加長(zhǎng)度的。然而如果將替換操作變成插入操作,我們還能保證一定可以得到一個(gè)標(biāo)號(hào)嚴(yán)格升序的上升子序列嗎?顯然不能。比如一次插入操作在S[k]和S[k+1]之間,我們插入了一個(gè)a[i],但是如果此時(shí)有a[j]>S[k+1],那么a[j]的左邊是沒(méi)辦法構(gòu)造出一個(gè)長(zhǎng)度為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的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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