POJ2182 Lost Cows
POJ2182 Lost Cows
題目概述
題目概述
給出一個從\(1-N\)這個\(N\)個數字的前面比它大的數字的個數,輸出原始的輸入序列.輸入首先是\(N\),然後是\(N-1\)個整數,表示從第二個數開始,它前面有多少個數字比它大.輸入資料規模:
\[1\leq N \leq 8\cdot10^3 \]
題目分析
從最後一個元素開始,既然前面比它大的數字有\(a[n]\)個,那麼它是\(1\sim N\)中第\(pre[n]+1\)大的數字,然後用同樣的方法可以求出倒數第二個,倒數第三個,\(\ldots\).這裡面注意之前已經調出的數字在後面的排序中不應該出現,可以用一個數組標記這個數此前有沒有使用,可以在\(O(n)\)
利用樹狀陣列的特性,可以在\(O(\log(n))\)時間內找到剩下的數中的第\(pre_i +1\)大的數字.樹狀陣列的特性是一個節點可以控制前面幾個節點,比如\(lowbit(4)=4\),表明前面的\(tree[1],tree[2],tree[3],tree[4]\)的改變都可以影響\(tree[4]\).設定\(tree[i]=lowbit(i)\),表示數\(i\)前面的有多少個是改變會影響\(tree[i]\)的值,在初始時而且\(sum(i)\)恰好表示的是\(i\)是第幾個數.當某一個數\(k\)被取出來後,通過修改\(tree[k]\)
以題目中給出的樣例來說,記過初始化後tree
:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
1 | 2 | 1 | 4 | 1 |
從後向前,查詢第一個數,得到的是1
,然後把tree[1]
減一,然後與tree[1]
相關的都會減一,得到
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 1 | 1 | 3 | 1 |
然後是計算sum(x)
為2
的x
得到的是3
,然後add(3,-1)
得到:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 1 | 0 | 2 | 1 |
然後是就散sum(x)
為3
時的x
得到x
是4
,然後add(4,-1)
得到:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 1 | 0 | 1 | 1 |
然後是就散sum(x)
為2
時的x
得到x
是5
,然後add(5,-1)
得到:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 1 | 0 | 1 | 0 |
最後是就是那sum(x)
為1
時的x
得到2
,再計算add(2,-1)
得到:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
佔坑:一定是糊塗了,沒法表述清楚,後面有時間一定更新重寫.
程式碼
/*
* @Author: Shuo Yang
* @Date: 2020-08-05 11:41:18
* @LastEditors: Shuo Yang
* @LastEditTime: 2020-08-05 12:34:42
* @FilePath: /Code/2182.cpp
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int pre[N];
int tree[N];
int n;
inline int lowbit(int x){
return x & -x;
}
void add(int x, int v){
while(x <= n){
tree[x] += v;
x += lowbit(x);
}
}
int sum(int x){
int ans = 0;
while( x > 0){
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int binary_find(int v){
int l = 1;
int r = n;
while(l < r){
int mid = (l + r)/2;
if( sum(mid) < v){
l = mid + 1;
}else{
r = mid;
}
}
// printf("l=%d\n",l);
return l;
}
int buf[N];
int main(int argc, const char** argv) {
scanf("%d", &n);
tree[1] = lowbit(1);
for(int i = 2; i <= n; ++i){
scanf("%d",&pre[i]);
tree[i] = lowbit(i);
}
for(int i = n; i > 0;--i){
int x = binary_find(pre[i]+1);
// printf("i=%d,x=%d",i,x);
add(x, -1);
buf[i] = x;
}
for(int i = 1; i <= n; ++i ){
printf("%d\n",buf[i]);
}
return 0;
}