dp 樹狀陣列

2022-06-30 09:03:11 字數 2512 閱讀 3995

給定乙個長度為 n

'>n

的序列 a

'>a

,求 a

'>a

有多少個長度為 m

'>m

的嚴格遞增子串行。

輸入格式

第一行包含整數 t

'>t

t,表示共有 t

'>

t 組測試資料。

每組資料,第一行包含兩個整數 n

'>

n 和 m

'>

m。第二行包含 n

'>

n 個整數,表示完整的序列 a

'>

a。輸出格式

每組資料輸出乙個結果,每個結果佔一行。

輸出格式為case #x: y,x

'>x

為資料組別序號,從 1

'>1

1 開始,y

'>y

y 為結果。

由於答案可能很大,請你輸出對 109+

7'>1e9+7

取模後的結果。

資料範圍1≤

t≤100'>1≤t≤1001≤

m≤n≤

1000

'>1≤m≤n≤1000∑i

=1tn

i×mi

≤107'>∑ti=1ni×mi≤1e7

序列中的整數的絕對值不超過10

9'>1e9

。輸入樣例:

2

3 21 2 3

3 23 2 1

輸出樣例:
case #1: 3

case #2: 0

f[maxn][maxn];//以第i個結尾時,有j個遞增的方案數

優化之前的**時這樣的:

#include#include

#include

using

namespace

std;

const

int maxn=1e3+100

;const

int mod=1e9+7

;int

a[maxn],t;

int f[maxn][maxn];//

以第i個結尾時,有j個遞增的方案書

intn,m;

intmain()

f[1][1]=1

;

for(int i=1;i<=n;i++)

for(int i=2;i<=n;i++)

f[i][j+1]%=mod;} }

}int ans=0

;

for(int i=1;i<=n;i++)

printf(

"case #%d: %d\n

",++kase,ans);

} }

然後可以用線段樹或者樹狀陣列優化掉一維

#include#include

#include

typedef

long

long

ll;using

namespace

std;

const

int maxn=1e3+100

;const

int mod=1e9+7

;int

a[maxn],t;

int f[maxn][maxn];//

以第i個結尾時,有j個遞增的方案數

intn,m;

int cnt=0

; int

c[maxn];

intnum[maxn];

int lowbit(int

x)void add(int x,intk)}

int getsum(int

x)

return

ans;

}int

main()

sort(num+1,num+cnt+1

); cnt=unique(num+1,num+cnt+1)-(num+1

);

for(int i=1;i<=n;i++)

for(int i=1;i<=n;i++)

for(int j=2;j<=m;j++)

for(int i=1;i<=n;i++)

}int ans=0

;

for(int i=1;i<=n;i++)

printf(

"case #%d: %d\n

", ++kase,ans);

}}

數字DP 樹狀陣列

考慮如何計算f l r f l r 很顯然,可以分別計算l,r l,r 的二進位制中1的個數,然後減去 最大公共字首的1的個數 2。考慮如何統計每一對l,r l,r 的最大字首中1的個數,可以用數字dp。記f i j 1 0 1 0 f i j 1 0 1 0 表示前i i 位,最大公共字首中1的個...

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...