HDU 2838 DP 樹狀陣列維護帶權排序

2022-07-04 12:36:14 字數 1215 閱讀 9912

題目鏈結

題目大意:每頭牛有個憤怒值,每次交換相鄰兩個數進行公升序排序,$cost=val_+val_$,求$\min \sum cost_$

解題思路

按輸入順序dp:

第i的值val的最小cost=當前數的逆序數個數*val+當前數的逆序數和

相當於每次只把這個val同逆序的數做交換,$\sum val_=rev*val$ , $\sum val_=\sum rev$

無後效性原則體現在,當前計算的cost只於前面的數有關,而且對順序沒有影響(逆序數隨你怎麼排了)

求逆序數個數和逆序數和都可以通過樹狀陣列在$o(logn)$內完成

樹狀陣列對於每個val,$update(val,1)$,即每個val點的值是1

這樣$rev=i-getindex(val)$

原理是,樹狀陣列是按從小到大維護的,輸入順序i(從1開始)-前面數個數(包含自身)=本來應該在後面,卻跑到前面數的個數

本題的乙個trick就是val不可重,所以$update(val,val)$ ,即每個val點的值是val

這樣$\sum=getsum(n)-getsum(val)$,即整個序列已經更新的值和(i~n此時都是0)-當前值前面的和=逆序數和

#include "

cstdio

"#include

"map

"#include

"cstring

"#include

"algorithm

"using

namespace

std;

#define ll long long

#define maxn 100005ll sum[maxn],index[maxn];

intval,n;

int lowbit(int x)

ll getsum(

intx)

return

ret;

}ll getindex(

intx)

return

ret;

}void update(int x,int s,int

idx)

}int

main()

printf(

"%i64d\n

",ans);

}}

樹狀陣列 hdu2689 hdu2838

題意 給定乙個正整數n,和乙個1 n的乙個排列,每個數可以和旁邊的兩個數的任意乙個交換,每交換一次總次數就要加一,問將這個排列轉換成乙個遞增的排列需要多少次交換?題意可以轉換成求這個排列的逆序對數。include include include include using namespace std...

hdu 2838 樹狀陣列水題

提議是給你乙個序列 讓你調整把它變成 從小到大排列的有序序列 沒調動兩個為兩權值之和 問最小的權值和是多少 給個數列 1 4 2 3 5 對每乙個位置數 需要交換的比為前面比它大的數 或後面比它小的數 包含了最小值在裡面了 比如pi前面有5個數比它大 則就需要把這5個數和pi交換 交換的權值就是這5...

hdu 2227 樹狀陣列 dp

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