BZOJ3192 JLOI2013 刪除物品

2022-02-28 14:58:49 字數 1255 閱讀 9105

箱子再分配問題需要解決如下問題:

(1)一共有n個物品,堆成m堆。

(2)所有物品都是一樣的,但是它們有不同的優先順序。

(3)你只能夠移動某堆中位於頂端的物品。

(4)你可以把任意一堆中位於頂端的物品移動到其它某堆的頂端。若此物品是當前所有物品中優先順序最高的,可以直接將之刪除而不用移動。

(5)求出將所有物品刪除所需的最小步數。刪除操作不計入步數之中。

(6)只是乙個比較難解決的問題,這裡你只需要解決乙個比較簡單的版本:

不會有兩個物品有著相同的優先順序,且m=2

第一行是包含兩個整數n1,n2分別表示兩堆物品的個數。

接下來有n1行整數按照從頂到底的順序分別給出了第一堆物品中的優先順序,數字越大,優先順序越高。

再接下來的n2行按照同樣的格式給出了第二堆物品的優先順序。

對於每個資料,請輸出乙個整數,即最小移動步數。

3 3145

2731<=n1+n2<=100000

這玩意真的沒想到怎麼做...想了一堆奇奇怪怪的做法沒乙個有用...(雖然平衡樹維護區間翻轉是沒啥問題的...但是好難寫)

然後就悄咪咪翻了一下題解。發現做法很妙啊..

把這兩個棧拼在一起,那麼移動的是分界點,那麼每一次移動之後增加的代價就是中間還在的數目,這個很容易就可以用bit維護。那麼模擬這個分界點移動的過程,就可以\(o(nlogn)\)解決了。

細節問題注意一下就好了=_=。就是對當前分界點這個指標在最大數的右邊還是左邊分類討論一下,至於最大值可以排序一下就可以保證每次都是取最大了。

#include using namespace std;

typedef long long ll;

const int n = 200010;

int n, m, a[n];

ll c[n];

struct task t[n];

bool operator < (task a, task b)

#define lowbit(i) (i & -i)

void add(int x, int v)

ll query(int x)

int main() ;

add(i, 1);

} sort(t + 1, t + n + 1);

ll ans = 0;

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

cout << ans << endl;

}

BZOJ3192 JLOI2013 刪除物品

原題位址 自己想的奇葩做法 對於乙個優先順序為x的物品,考察該物品下方優先順序大於x物品的優先順序被分成了多少個連續段 舉個例子,如x 4,該物品下方物品的優先順序有5,6,7,9,10,13,14,19,則段數為4 則該物品需要被移動的次數k 段數 2 優先順序為x 1的物品在該物品下方?1 0 ...

bzoj 3192 JLOI2013 刪除物品

因為只有兩堆,所以方案數顯然唯一。可以將兩隊合併成乙個陣列,用樹狀陣列維護,每次刪乙個點的代價就是最大值到次大值得距離。一開始假裝兩堆中間有個無限大的數。有點坑點,裡有注釋。code include include include include include include define ll ...

bzoj3192 JLOI2013 刪除物品

description 箱子再分配問題需要解決如下問題 1 一共有n個物品,堆成m堆。2 所有物品都是一樣的,但是它們有不同的優先順序。3 你只能夠移動某堆中位於頂端的物品。4 你可以把任意一堆中位於頂端的物品移動到其它某堆的頂端。若此物品是當前所有物品中優先順序最高的,可以直接將之刪除而不用移動。...