POJ-2182-Low Cows
这道题是一道线段树。模板线段树。
不慌。没有暴力不能解决的问题。
8000的数据还是可以暴力跑一下的嘻嘻。
题目大意:已知每头牛前面有几头牛比他矮。问原序列。
pre[]保存前面有几头牛比当前矮
暴力的话从后往前处理即可。答案就是第pre[]+1大的数字,另外一个数组num[]保存1~n的值,把处理过的数值直接赋值为-1就行,在剩下的序列中选择即可。
poj万能头CE了,改改就行
暴力代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 8e3 + 10;
int n;
int pre[N];
int ans[N];
int num[N];
int main()
{
cin >> n;
pre[1] = 0;
for (int i = 1; i <= n; i++)
{
num[i] = i;
}
for (int i = 2; i <= n; i++)
{
scanf ("%d", &pre[i]);
}
for (int i = n; i >= 1; i--)
{
int k = 0;
for (int j = 1; j <= n; j++)
{
if (num[j] != -1)
{
k++;
if (k == pre[i] + 1)
{
ans[i] = num[j];
num[j] = -1;
break;
}
}
}
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << endl;
}
return 0;
}
时间复杂度O(n^2);
线段树代码一样的思路,从后往前。就是时间复杂度低些:
其一是普通二叉树,含结构体
代码部分:
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e4 + 10;
struct node
{
int l, r;
int len;
}tree[4 * N];
int pre[N];
int ans[N];
int n;
void BuildTree(int left, int right, int u)
{
tree[u].l = left;
tree[u].r = right;
tree[u].len = right - left + 1;
if (left == right)
{
return ;
}
BuildTree(left, (left + right) >> 1, u << 1);
BuildTree(((left + right) >> 1) + 1, right, (u << 1) + 1);
}
int query(int u, int num)
{
tree[u].len--;
if (tree[u].l == tree[u].r)
{
return tree[u].l;
}
if (tree[u << 1].len >= num)//左子树的个数足够,访问左子树
{
return query(u << 1, num);
}
else//不够,访问右子树
{
return query((u << 1) + 1, num - tree[u << 1].len);
}
}
int main()
{
cin >> n;
pre[1] = 0;
for (int i = 2; i <= n; i++)
{
scanf ("%d", &pre[i]);
}
BuildTree(1, n, 1);
for (int i = n; i >= 1; i--)
{
ans[i] = query(1, pre[i] + 1);
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << endl;
}
return 0;
}
完全二叉树实现:直接访问地址效率较高
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 1e4 + 10;
int pre[N];
int ans[N];
int tree[4 * N];
int n;
void BuildTree(int n, int last)
{
for (int i = last; i < last + n; i++)
{
tree[i] = 1;
}
while (last != 1)
{
for (int i = last / 2; i < last; i++)
{
tree[i] = tree[i * 2] + tree[i * 2 + 1];
}
last /= 2;
}
}
int query(int u, int num, int last)
{
tree[u]--;
if (!tree[u] && u >= last)
{
return u;
}
if (tree[u << 1] >= num)
{
return query(u << 1, num, last);
}
else
{
return query((u << 1) + 1, num - tree[u << 1], last);
}
}
int main()
{
cin >> n;
pre[1] = 0;
int last = 1 << ((int)(log(n) / log(2)) + 1);//最底层最左边的结点
for (int i = 2; i <= n; i++)
{
scanf ("%d", &pre[i]);
}
BuildTree(n, last);
for (int i = n; i >= 1; i--)
{
ans[i] = query(1, pre[i] + 1, last) - last + 1;
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << endl;
}
return 0;
}