hdu5125 樹狀陣列 dp

2022-05-15 04:20:45 字數 1447 閱讀 1794

hdu5125 他說的是n個人每個人都有兩個氣球a,b,氣球各自都有相應的體積,現在讓他們按照序號排列好來,對他們的a氣球體積值計算最長上公升子串行,對於這整個排列來說有m次機會讓你將a氣球替換成b氣球(允許不使用完),問最後的最長上公升子串行 的長度是多少,哈哈,當然用dp的思想我們很容易就能知道狀態的轉移 dp[1000][1000][2],但是苦於狀態轉移的複雜度太大了達到了 n*n*m肯定受不了,那好我們可以列出這個方程的轉移方法

(0表示a氣球1為b氣球)

dp[i][j][0]=max(  dp[k][j][0]     +1(a[k]

dp[i][j][1]=max(  dp[k][j-1][0] +1(a[k]

想想優化方法 看來還是需要有換個想法的能力 啊 !

通過建立m棵樹狀陣列 第j棵樹 表示 使用了 j 個 能 量 的 時 候 每個位置所能到達的最高點,說清楚一點就是講這n*2個氣球體積進行離散,得到了樹狀陣列的每個節點從第0個人列舉到第n-1個,比如到達了第i個人 那麼 到達他時使用了j個機會的 方案是不是 就是去找比ai(假設離散後在k這個位置)小的那些氣球使用j個機會時達到的最長序列加1呢,好那麼現就使用樹狀陣列去計算出前k-1 項的 最大值s,然後將s這個值插入當前這個樹狀陣列中 ,那麼現在 我們考慮使用b氣球可以去j-1 這棵樹上去找 然後得到的值加1 插入第j棵樹上,哇這樣很完美啊! 瞬間將複雜度減了2個0,這樣一直不斷地做下去直到結束.

#include #include 

#include

#include

using

namespace

std;

const

int maxn=1005

;int

a[maxn],b[maxn];

int c[maxn][maxn*2],h[maxn*2

],l;

int lowbit(int

x)void add(int loc, int floor,intv)}

int sum(int loc, int

floor)

return

ans;

}int

main()

memset(c,

0,sizeof

(c));

sort(h,h+l);

l=unique(h,h+l)-h;

int ans=1

;

for(int i=0; ii)

val = sum(loca-1,0

); ans=max(ans,val+1

); add(loca,

0,val+1

); }

printf(

"%d\n

",ans);

}return0;

}

view code

hdu 2227 樹狀陣列 dp

題意是求乙個數列的不遞減的子串行的個數 很顯然,如果只用dp來做的話時間是o n n 因為dp i 為前i個數可能的方案,則狀態轉移方程為dp i sum dp j j 先對num按數來進行排序,這道題因為資料較大 用到了離散化 因為更新是是按原序更新的,及i之前的num j 一定比num i 小,...

hdu5489 樹狀陣列 dp

2015 10 06 21 49 54 這題說的是個給了乙個陣列,然後刪除任意起點的乙個連續的l個數,然後求最長遞增子串行 是遞增,不是非遞減 用乙個樹狀陣列維護一下就ok了 include include include include include using namespace std co...

hdu 5542(樹狀陣列優化dp)

題意 求n個數中長度為m的上公升子串行的個數 解題思路 dp i j 表示第i個數長度為j的上公升序列的個數。dp i j sum,這裡的時間複雜度有o n 會超時,所以這裡要有優化。其實可以將a i 離散化,對於每乙個j,構造乙個樹狀陣列,這樣求sum就可以用樹狀陣列的求和了,時間複雜度可以降為o...