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 #includeview code#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;
}
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...