謎一樣的牛 樹狀陣列

2022-09-07 07:12:10 字數 1769 閱讀 7977

有n頭奶牛,已知它們的身高為 1~n 且各不相同,但不知道每頭奶牛的具體身高。現在這n頭奶牛站成一列,已知第i頭牛前面有ai頭牛比它低,求每頭奶牛的身高。

輸入格式

第1行:輸入整數n。

第2…n行:每行輸入乙個整數ai,第i行表示第i頭牛前面有ai頭牛比它低。

(注意:因為第1頭牛前面沒有牛,所以並沒有將它列出)

輸出格式

輸出包含n行,每行輸出乙個整數表示牛的身高。

第i行輸出第i頭牛的身高。

資料範圍

1≤n≤105

輸入樣例:51

210輸出樣例:24

531先說一下樹狀陣列,樹狀陣列是個很神奇的資料結構,定義tr[x]為區間長度為lowbit(x),末尾時x的區間和,就是[x-lowbit(x)+1,x]的區間和。

lowbit(x)=x&-x;

int

lowbit

(int x)

tr[x]是[x-lowbit(x)+1,x]的和,那麼如果想求[1,n]的和該怎麼求,tr[x-lowbit(x)]是不是剛好與tr[x]無縫相連,那麼一直這項拼接下去直到區間起點為1就可以了(可以證明這樣是一定存在的)

int

sum(

int x)

如果還想修改某個點的值那該怎麼做呢,假設要修改點x位置的值,只需要找一下有那麼些 tr 區間是包含點x的,tr[x]是一定得,然後得繼續向後找,

假設x二進位制為101011:

lowbit(x)=1,x+lowbit=101100,lowbit(x+lowbit)=100,

x+lowbit-lowbit(x+lowbit(x))=101000void

add(

int x,

int d)

//第x個數加d

所以樹狀陣列支援單點修改,區間求和,比線段樹作用單一但比線段樹**短

然後再看這道題,每頭牛只知道它前面都幾頭牛比他低,如果ai=0,那麼i就是前i個的最小值,最後乙個0呢就一定是1;ai=j,它就是前i個的第j+1小,如果前i個數已經確定那i就是第j和第j+1中間的數,那如果第j和第j+1之間沒有數了就錯誤了,所以不能先確定前面的數,只能先i確定後面的數,那麼前i個數就會有乙個可能的集合,再這個集合裡面找到找第j+1小的數就是第i頭牛的高。

初始化的集合一定是1到n,令每個數都等1,已經確定過得高度就改為0,所以第j+1小的點就是第乙個字首和等於j+1的點,就可以用樹狀陣列啦

#include

using

namespace std;

typedef

long

long ll;

const

int n=

100010

;int n,a[n]

,tr[n]

;int

lowbit

(int x)

void

add(

int x,

int d)

intsum

(int x)

intmain()

//l是小於等於ai的最大點

a[i]

=l+1

;add

(l+1,-

1);//不能在第0個位置修改,能求和

}for

(int i=

1;i<=n;i++

) cout<

}

再貼一道一模一樣的題:

謎一樣的牛 樹狀陣列

有n頭奶牛,已知它們的身高為 1 n 且各不相同,但不知道每頭奶牛的具體身高。現在這n頭奶牛站成一列,已知第i頭牛前面有ai頭牛比它低,求每頭奶牛的身高。輸入格式 第1行 輸入整數n。第2 n行 每行輸入乙個整數ai,第i行表示第i頭牛前面有ai頭牛比它低。注意 因為第1頭牛前面沒有牛,所以並沒有將...

244 謎一樣的牛(樹狀陣列)

有n頭奶牛,已知它們的身高為 1 n 且各不相同,但不知道每頭奶牛的具體身高。現在這n頭奶牛站成一列,已知第i頭牛前面有ai 頭牛比它低,求每頭奶牛的身高。輸入格式 第1行 輸入整數n。第2 n行 每行輸入乙個整數ai 第i行表示第i頭牛前面有ai 頭牛比它低。注意 因為第1頭牛前面沒有牛,所以並沒...

樹狀陣列 二分 謎一樣的牛

有n頭奶牛,已知它們的身高為 1 n 且各不相同,但不知道每頭奶牛的具體身高。現在這n頭奶牛站成一列,已知第i頭牛前面有ai頭牛比它低,求每頭奶牛的身高。輸入格式 第1行 輸入整數n。第2 n行 每行輸入乙個整數ai,第i行表示第i頭牛前面有ai頭牛比它低。注意 因為第1頭牛前面沒有牛,所以並沒有將...