这道题还是很经典的
给出了一个序列,代表的是比该位置的牛靠前站的且序号比他小的牛的个数
然后思想类似于2828,正序看的话,看不出有什么规律,但是逆序的话,就能看出当前序列的最后一头牛的编号是可以确定的,就相当于有一个队列,初始化全为1,有牛占了就把相应位置变为0,然后我们只管那些位置为1的地方,往里一头一头的塞牛,塞一头,能塞的地方就少一个,但是和之前塞过的就没关系了,这也符合题目中,只管比该位置靠前的且序号小的 这个条件
/*
ID: sdj22251
PROG: inflate
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 10000
#define INF 1000000000
#define eps 1e-7
#define PI 3.1415926535898
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct node
{
int left, right, mid;
int cnt;
}tree[4 * MAXN];
int a[MAXN], ans[MAXN];
void make_tree(int s, int e, int C)
{
tree[C].left = s;
tree[C].right = e;
tree[C].mid = (s + e) >> 1;
tree[C].cnt = tree[C].right - tree[C].left + 1;
if(s == e) return;
make_tree(s, tree[C].mid, L(C));
make_tree(tree[C].mid + 1, e, R(C));
}
void insert(int p, int x, int C)
{
tree[C].cnt--;
if(tree[C].left == tree[C].right)
{
ans[x] = tree[C].left;
return;
}
if(tree[L(C)].cnt > p)
insert(p, x, L(C));
else insert(p - tree[L(C)].cnt, x, R(C));
}
int main()
{
int n;
scanf("%d", &n);
make_tree(1, n, 1);
for(int i = 2; i <= n; i++)
scanf("%d", &a[i]);
for(int i = n; i >= 1; i--)
insert(a[i], i, 1);
for(int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
return 0;
}
下面是树状数组做法
其实还是那个原理 ,倒序推。刚开始的时候把n个位置都准备好,然后塞牛,塞一头就把相关的位置删1,表示之前能站的地方少了一个。
然后倒序找位置的时候,用的是二分查找。因为树状数组的和,也是有序的
/*
ID: sdj22251
PROG: inflate
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 10000
#define INF 1000000000
using namespace std;
int a[MAXN];
int ans[MAXN];
int t[MAXN], n;
int lowbit(int x)
{
return x & -x;
}
void modify(int x, int v)
{
for(int i = x; i <= n; i += lowbit(i))
a[i] += v;
}
int getsum(int x)
{
int sum = 0;
for(int i = x; i > 0; i -= lowbit(i))
sum += a[i];
return sum;
}
int search(int x)
{
int low = 1;
int high = n;
int mid;
while(low <= high)
{
mid = (low + high) >> 1;
int tmp = getsum(mid);
if(x <= tmp) high = mid - 1;
else low = mid + 1;
}
return low;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
modify(i, 1);//把这些位置准备好,表示都可以站牛
for(int i = 2; i <= n; i++)
scanf("%d", &t[i]);
for(int i = n; i >= 1; i--)
{
ans[i] = search(t[i] + 1);
modify(ans[i], -1); //这头牛占了一个位置,把之后有关系的地方都删掉这个1
}
for(int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
return 0;
}