題目描述
有n頭奶牛,已知它們的身高為 1~n 且各不相同,但不知道每頭奶牛的具體身高。
現在這n頭奶牛站成一列,已知第i頭牛前面有ai頭牛比它低,求每頭奶牛的身高。
輸入格式
第1行:輸入整數n。
第2…n行:每行輸入乙個整數ai,第i行表示第i頭牛前面有ai頭牛比它低。
(注意:因為第1頭牛前面沒有牛,所以並沒有將它列出)
輸出格式
輸出包含n行,每行輸出乙個整數表示牛的身高。
第i行輸出第i頭牛的身高。
資料範圍
1≤n≤105
輸入樣例:
512
10
輸出樣例:
245
31
對於做資料結構的題目,資料結構本身不難,難的是我們怎麼把他抽象成用資料結構操作。
題目資料給出每頭牛前面有幾頭牛比它矮,對於樣例來看
第1頭牛前面沒有牛、第2頭牛前面有1頭牛比他矮、第3頭牛前面有2頭牛比他矮、第4頭牛前面有1頭牛比他矮、第5頭牛前面有0頭牛比他矮。
資料 :0 1 2 1 0
我們正向不好看,倒著看。
最後一頭牛,前面沒有比他矮的,說明它是最矮的 。1、2、3、4、5,選擇1作為身高。
倒數第2頭牛,前面有1頭牛比他矮,說明它是剩餘身高中第二矮的。2、3、4、5,選擇3作為身高。
倒數第3頭牛,前面有2頭牛比他矮,說明它是剩餘身高中第三矮的。2、4、5,選擇5作為身高。
倒數第4頭牛,前面有1頭牛比他矮,說明它是剩餘身高中第二矮的。2、4,選擇4作為身高。
倒數第5頭牛,前面有0頭牛比他矮,說明它是剩餘身高中最矮的。2,選擇2作為身高。
答案即 2、4、5、3、1
所以,我們根據分析的結論可以得出,對於第i頭牛,他的身高=剩餘身高中第k+1矮的(k是前面比他矮的牛)。
邏輯操作:
倒序遍歷每一頭牛
對於每一頭牛
在剩餘的身高中找第k+1小的。
刪除找到的身高
如果用二重迴圈肯定會tle。
查詢剩餘身高我們盡量希望是log級別的,因為我們要遍歷所有牛不能優化,查詢盡可能的更快。
所以查詢我們要使用二分查詢,二分查詢需要在乙個有序陣列裡,考慮到還有刪除操作,我們想到了樹狀陣列。
刪除操作很簡單。
分析查詢:
我們把樹狀陣列的初始值附為1,代表這個身高還沒用過。
對於第i頭牛,他前面有m頭牛比他矮,二分查詢sum(x)>=m+1,也就是找第乙個》=m+1的下標,下標就是該牛的身高。
sum函式是樹狀陣列的字首和。
sum(1 ~ n)一定是乙個單調遞增的數,因為我們初始值為1,如果用過乙個身高,則變成0,所以無論怎麼變,sum(1 ~ n)一定是乙個遞增的數。
比如 :
剩餘身高 :有 1 2 3 4 5 (1、4被用過了)
樹狀陣列維護的陣列 為 0 1 1 0 1
sum函式維護的字首和為:0 1 2 2 3
如果我們找剩餘身高中第2矮的,二分查詢第乙個sum(x)的下標》=2的,下標3就是該牛的身高。
整個時間複雜度o(n * logn * logn)
code:
#include
#include
#include
typedef
long
long ll;
const ll n=
1e5+10;
using
namespace std;
ll h[n]
,a[n]
,tr[n]
,ans[n]
;ll n;
ll lowbit
(ll x)
void
add(ll pos,ll x)
ll sum
(ll x)
intmain()
add(r,-1
);ans[i]
=r;}
for(
int i=
1;i<=n;i++
) cout<
}
樹狀陣列 二分 謎一樣的牛
有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頭牛前面沒有牛,所以並沒有將...
謎一樣的牛 樹狀陣列
有n頭奶牛,已知它們的身高為 1 n 且各不相同,但不知道每頭奶牛的具體身高。現在這n頭奶牛站成一列,已知第i頭牛前面有ai頭牛比它低,求每頭奶牛的身高。輸入格式 第1行 輸入整數n。第2 n行 每行輸入乙個整數ai,第i行表示第i頭牛前面有ai頭牛比它低。注意 因為第1頭牛前面沒有牛,所以並沒有將...