考慮用樹狀陣列求解,簡單的暴力會超時。
大概思路:
每個數會和前面比它大的數交換,會和後面比它小的數交換,所以每個數交換的總次數為前面比這個數大的數的個數+後面比這個數小的個數,下面的**用b[i]維護這個個數和。
如何求呢?
用樹狀陣列儲存每個數出現的次數。
第一次正向遍歷,每次將資料出現的次數加入到樹狀陣列中,並更新b[i],更新的值為當前遍歷的個數減去小於a[i](當前數)的個數。
然後清空樹狀陣列。
第二次逆向遍歷,剛好可以找後面比a[i]小的數的個數,也是每次更新b[i]。
最後對整個b[i]進行等差數列求和的計算。
#
include
using
namespace std;
typedef
long
long ll;
const
int maxn =
1e6+5;
ll a[maxn]
,b[maxn]
;ll tr[maxn]
;int n;
void
update
(int a,
int b)
ll query
(int x)
intmain()
memset
(tr,0,
sizeof
(tr));
for(
int i=n;i>=
1;i--
) ll ans =0;
for(
int i=
1;i<=n;i++
) cout<
'\n'
;return0;
}
注意:
樹狀陣列是在以a[i]為下標的位置加一,做樹狀陣列的更新時,一定是要更新到最大的數,即a[i]所能代表的最大值
#
include
using
namespace std;
typedef
long
long ll;
const
int n =
1e6+5;
ll a[n]
,b[n]
,tr[n]
;int n;
void
add(
int p,
int x)
ll sum
(int p)
intmain()
for(
int i=
1;i) tr[i]=0
;for
(int i=n;i;i--
) ll ans =0;
for(
int i=
1;i<=n;i++
) ans+=b[i]
*(b[i]+1
)/2;
cout<
'\n'
;return0;
}
acwing 藍橋杯 小朋友排隊 (樹狀陣列)
題目鏈結 初始時,對於小朋友i來說,前面比他高的人數加上後面比他矮的人數就是這個小朋友將要交換的次數。利用樹狀陣列,第一遍求前面比他高的人數 第二遍求後面比他矮的人數 include using namespace std const int n 1e6 9 int tr n h n typedef...
小朋友排隊 樹狀陣列
問題 1439 藍橋杯 歷屆試題 小朋友排隊 時間限制 1sec 記憶體限制 128mb 提交 1083 解決 170 題目描述 n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是0...
藍橋 小朋友排隊 樹狀陣列
思路 樹狀陣列處理逆序對 求前面有多少個數比當前這個大 正著插 求後面有多少個數比當前這個小 反著插 求出f陣列和b陣列即可 下面是ac include include include include include include include define ll long long defin...