一个长度为M的正整数数组A,表示从左向右的地形高度。测试一种加农炮,炮弹平行于地面从左向右飞行,高度为H,如果某处地形的高度大于等于炮弹飞行的高度H(A[i] >= H),炮弹会被挡住并落在i - 1处,则A[i - 1] + 1。如果H <= A[0],则这个炮弹无效,如果H > 所有的A[i],这个炮弹也无效。现在给定N个整数的数组B代表炮弹高度,计算出最后地形的样子。
例如:地形高度A = {1, 2, 0, 4, 3, 2, 1, 5, 7}, 炮弹高度B = {2, 8, 0, 7, 6, 5, 3, 4, 5, 6, 5},最终得到的地形高度为:{2, 2, 2, 4, 3, 3, 5, 6, 7}。
Input
第1行:2个数M, N中间用空格分隔,分别为数组A和B的长度(1 <= m, n <= 50000)
第2至M + 1行:每行1个数,表示对应的地形高度(0 <= A[i] <= 1000000)。
第M + 2至N + M + 1行,每行1个数,表示炮弹的高度(0 <= B[i] <= 1000000)。
Output
输出共M行,每行一个数,对应最终的地形高度。
Input示例
9 11
1
2
0
4
3
2
1
5
7
2
8
0
7
6
5
3
4
5
6
5
Output示例
2
2
2
4
3
3
5
6
7
思路:
利用线段树,查找需要更新的点并做更新。
方法一:指针做
#include <iostream>
using namespace std;
const int MAXN = 50005;
struct Node
{
int left;
int right;
int maxVal;
Node *leftChild;
Node *rightChild;
Node(int a, int b)
{
left = a;
right = b;
leftChild = NULL;
rightChild = NULL;
}
};
int m, n;
int a[MAXN];
int b[MAXN];
Node* build(int l, int r)
{
Node *p = NULL;
p = new Node(l, r);
if (l == r)
{
p->maxVal = a[l];
return p;
}
int mid = l + (r - l) / 2;
p->leftChild = build(l, mid);
p->rightChild = build(mid + 1, r);
p->maxVal = max(p->leftChild->maxVal, p->rightChild->maxVal);
return p;
}
int find(int v, Node *p)
{
if (p->maxVal >= v)
{
if (p->left == p->right)
{
return p->left;
}
else if (p->leftChild->maxVal >= v)
{
return find(v, p->leftChild);
}
else
{
return find(v, p->rightChild);
}
}
return 0;
}
void update(int index, Node *p)
{
if (index <= p->right && index >= p->left)
{
if (p->left == p->right)
{
p->maxVal++;
a[p->left]++;
}
else if (index <= p->leftChild->right)
{
update(index, p->leftChild);
p->maxVal = max(p->maxVal, p->leftChild->maxVal);
}
else
{
update(index, p->rightChild);
p->maxVal = max(p->maxVal, p->rightChild->maxVal);
}
}
}
int main()
{
cin >> m >> n;
for (int i = 1; i <= m; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
cin >> b[i];
}
Node *top = build(1, m);
for (int i = 1; i <= n; i++)
{
if (b[i] <= a[1])
{
continue;
}
int pos = find(b[i], top);
if (pos != 0)
{
update(pos - 1, top);
}
}
for (int i = 1; i <= m; i++)
{
cout << a[i] << endl;
}
return 0;
}
方法二:数组做
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 50005;
#define lChild pos << 1
#define rChild (pos << 1) | 1
struct Node
{
int maxVal;
int left, right;
};
Node tree[MAXN << 2];
int m, n;
int a[MAXN];
int b[MAXN];
void build(int pos, int left, int right)
{
tree[pos].left = left;
tree[pos].right = right;
if (left == right)
{
tree[pos].maxVal = a[left];
return;
}
int mid = left + (right - left) / 2;
build(lChild, left, mid);
build(rChild, mid + 1, right);
tree[pos].maxVal = max(tree[lChild].maxVal, tree[rChild].maxVal);
}
int find(int pos, int v)
{
if (tree[pos].maxVal >= v)
{
if (tree[pos].left == tree[pos].right)
{
return tree[pos].left;
}
else if (tree[lChild].maxVal >= v)
{
return find(lChild, v);
}
else
{
return find(rChild, v);
}
}
return 0;
}
void update(int pos, int index)
{
if (tree[pos].left <= index && tree[pos].right >= index)
{
if (tree[pos].left == tree[pos].right)
{
tree[pos].maxVal++;
a[tree[pos].left]++;
}
else if (index <= tree[lChild].right)
{
update(lChild, index);
tree[pos].maxVal = max(tree[pos].maxVal, tree[lChild].maxVal);
}
else
{
update(rChild, index);
tree[pos].maxVal = max(tree[pos].maxVal, tree[rChild].maxVal);
}
}
}
int main()
{
cin >> m >> n;
for (int i = 1; i <= m; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
cin >> b[i];
}
build(1, 1, m);
for (int i = 1; i <= n; i++)
{
if (b[i] <= a[1])
{
continue;
}
int pos = find(1, b[i]);
if (pos > 0)
{
update(1, pos - 1);
}
}
for (int i = 1; i <= m; i++)
{
cout << a[i] << endl;
}
return 0;
}