消失之物,分治

2022-03-16 19:41:21 字數 1697 閱讀 9461

ftiasch 有 n 個物品, 體積分別是 w1, w2, ..., wn。 由於她的疏忽, 第 i 個物品丟失了。 「要使用剩下的 n - 1 物品裝滿容積為 x 的揹包,有幾種方法呢?」 -- 這是經典的問題了。她把答案記為 count(i, x) ,想要得到所有1 <= i <= n, 1 <= x <= m的 count(i, x) **。

view code

輸入格式

第1行:兩個整數 n (1 ≤ n ≤ 2 × 103) 和 m (1 ≤ m ≤ 2 × 103),物品的數量和最大的容積。

第2行: n 個整數 w1, w2, ..., wn, 物品的體積。

輸出格式

乙個 n × m 的矩陣, count(i, x)的末位數字

樣例樣例輸入

3 2

1 1 2

樣例輸出

11

1121

。。。我也不知道我是怎麼想到的,只記得一開始我打了個o(n2mlogn)的**交上後比暴力還慢。。。。

由此想到:合併揹包的複雜度為n2,所以與其合併揹包還不如乙個乙個地新增元素,由此可以想到:我們

考慮每個物品對複雜度的貢獻,期望為mlogn,那麼是不是可以用分治?so:假如我們有一棵線段樹,在

每乙個結點開乙個揹包,怎麼用呢?考慮每個物品對答案的貢獻,對線段樹的沒個非葉子節點:

假設某個節點控制範圍為l到r,則mid=l+r>>1;(廢話)那麼(l,mid)範圍內所有的點會對(mid+1,r)

的答案作出貢獻,所以把(l,mid)內每個物品單獨取出,加入到rc的揹包中,並且在考慮以rc為根的子樹時

把rc的揹包下傳以傳遞貢獻,下傳時直接memcpy即可;在葉子節點統計答案,直接輸出

1 #include 2

#define n 2003

3#define reg register

4using

namespace

std;

5int

n, m;

6int

w[n];

7int

pos[n];

8int f[n << 2

][n];

9void ask(const

int g, const

int l, const

intr)

14const

int mid = l + r >> 1, lc = g << 1, rc = g << 1 | 1

;15 f[lc][0] = f[rc][0] = 1;16

for (int i = 1; i <= m; ++i) f[lc][i] = f[rc][i] =f[g][i];

17for (reg int i = mid + 1; i <= r; ++i) 22}

23for (reg int i = l; i <= mid; ++i) 28}

29ask(lc, l, mid);

30 ask(rc, mid + 1

, r);31}

32int

main()

40 }

感謝loj碼風優化(貌似某位壓行大神也寫過?)

優化:1.其實不必在所有節點開揹包,在每層開乙個即可;

2.到達葉子節點可直接輸出答案,不必最後統計輸出;

BZOJ2287 消失之物 分治 DP

time limit 10 sec memory limit 128 mb submit status discuss ftiasch 有 n 個物品,體積分別是 w1 w2 wn 由於她的疏忽,第 i 個物品丟失了.要使用剩下的 n 1 物品裝滿容積為 x 的揹包,有幾種方法呢?這是經典的問題了。...

POJ Challenge消失之物

ftiasch 有 n 個物品,體積分別是 w1 w2 wn 由於她的疏忽,第 i 個物品丟失了。要使用剩下的 n 1 物品裝滿容積為 x 的揹包,有幾種方法呢?這是經典的問題了。她把答案記為 count i,x 想要得到所有1 i n,1 x m的 count i,x 第1行 兩個整數 n 1 n...

消失之物 s 題解

是不是很熟悉的開頭,哈哈,畢竟乙隻蒟蒻第一次寫題解多少有點緊張啊 本題來自hloj 1949 好了,切入正題 題面意思呢,就是給你n個物品,乙個m的揹包,接下來是w i 表示每個物品的重量,看起來很簡單,不過呢,有乙個物品丟了,你要輸出乙個 橫排的數值表示丟了第i個物品,縱列的數值表示要來填滿乙個容...