樹狀陣列與線段樹(二)

2022-01-10 10:20:35 字數 2891 閱讀 2934

樹狀陣列

1.小朋友排隊

n'>n

個小朋友站成一排。

現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。

每個小朋友都有乙個不高興的程度。

開始的時候,所有小朋友的不高興程度都是 0

'>0

。如果某個小朋友第一次被要求交換,則他的不高興程度增加 1

'>1

,如果第二次要求他交換,則他的不高興程度增加 2

'>2

(即不高興程度為 3

'>3

),依次類推。當要求某個小朋友第 k

'>k

次交換時,他的不高興程度增加 k

'>k

。請問,要讓所有小朋友按從低到高排隊,他們的不高興程度之和最小是多少。

如果有兩個小朋友身高一樣,則他們誰站在誰前面是沒有關係的。

輸入格式

輸入的第一行包含乙個整數 n

'>n

,表示小朋友的個數。

第二行包含 n

'>n

n 個整數 h1,

h2,…

,hn'>h1,h2,…,hn

,分別表示每個小朋友的身高。

輸出格式

輸出一行,包含乙個整數,表示小朋友的不高興程度和的最小值。

資料範圍1≤

n≤100000

'>1≤n≤1000000≤

hi≤1000000

'>0≤hi≤1000000

輸入樣例:

3

3 2 1

輸出樣例:
9
樣例解釋

首先交換身高為3和2的小朋友,再交換身高為3和1的小朋友,再交換身高為2和1的小朋友,每個小朋友的不高興程度都是3,總和為9。

解題思路:解題關鍵就是找到最少的交換次數,我們可能會想到氣泡排序法,他就是通過不斷的交換排序來實現的,因此我們可以大膽的假設一些規律,最少的交換次數==逆序對的個數。

對於氣泡排序來說,每次交換最多減少乙個逆序數

假設陣列有k個逆序對,

①至少需要交換k次,因此次數》=k

②在氣泡排序中,每次交換(ai,ai+1)且ai>ai+1,因此必然會使逆序數減1

綜上我們得出最少的交換次數==逆序對的個數

接下來,我們要求每乙個小朋友的逆序數,然後根據前n項和公式求出他的不高興數,在求解單個逆序數時,我們就用到樹狀陣列來統計在該陣列中,前方大於他的數和後方小於他的數,總和即為該數的逆序數。

**:

#include#include

using

namespace

std;

typedef

long

long

ll;const

int n=1000010

;int

tr[n],h[n];

ll con[n];

intn;

int lowbit(int

x)void add(int x,int

v)int query(int

x)int

main()

//計算前面比他大的數

long

long ans=0

;

for(i=0;i)

//計算後面比它小的數

memset(tr,0,sizeof

(tr));

for(i=n-1;i>=0;i--)

//總和

for(i=0;i)

ans+=con[i]*(con[i]+1)/2

; cout

}

差分1.差分

輸入乙個長度為n的整數序列。

接下來輸入m個操作,每個操作包含三個整數l, r, c,表示將序列中[l, r]之間的每個數加上c。

請你輸出進行完所有操作後的序列。

輸入格式

第一行包含兩個整數n和m。

第二行包含n個整數,表示整數序列。

接下來m行,每行包含三個整數l,r,c,表示乙個操作。

輸出格式

共一行,包含n個整數,表示最終序列。

資料範圍1≤

n,m≤

100000

'>1≤n,m≤100000,1

≤l≤r

≤n'>1≤l≤r≤n,−

1000≤c

≤1000

'>−1000≤c≤1000,−

1000≤整

數序列中

元素的值

≤1000

'>−1000≤整數序列中元素的值≤10001≤

n,m≤

100000

'>1≤l

≤r≤n

'>−

1000≤c

≤1000

'>−

1000≤整

數序列中

元素的值

≤1000

'>解題思路:

給定a[1],a[2],...a[n]構造查分陣列b[n],使得

a[i]=b[1]+b[2]+...b[i]

核心操作:將a[l~r]全部加上c,等價於b[l]+=c,b[r+1]-=c

1.a[1~l-1]無影響

2.a[l~r]加上了c

3.a[r+1~n]無影響

#includeusing

namespace

std;

const

int n=100010

;int

b[n],q[n];

void insert(int l,int r,int

c)int

main()

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

return0;

}

樹狀陣列與線段樹

推一下關於樹狀陣列的講解部落格 和線段樹的講解 package test2 public class 線段樹 int len a.length segtree t buildtree 0,len 1,a int sum0 2 query t,0,2 int sum1 3 query t,1,3 查詢...

樹狀陣列與線段樹(三)

找規律題 1.螺旋折線 如下圖所示的螺旋折線經過平面上所有整點恰好一次。對於整點 x,y 我們定義它到原點的距離 dis x,y 是從原點到 x,y 的螺旋折線段的長度。例如 dis 0,1 3,dis 2,1 9 給出整點座標 x,y 你能計算出 dis x,y 嗎?輸入格式 包含兩個整數 x,y...

線段樹與樹狀陣列學習總結 線段樹

點動成線 那麼就是說一條線段可以分成若干個點,再想想我們最常用的一維陣列,構成陣列的是乙個個的變數,如果把變數看成乙個個點,那麼陣列就是一條線了!而線段樹,就是一棵由線段構成的二叉樹,每個結點都代表一條線段 a,b 也就是我們前面說的一串變數 非葉子的結點所對應的線段都有兩個子結點,左兒子代表的線段...