1287 加农炮
题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注
一个长度为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
李陶冶 (题目提供者)
线段树 rmq[k]=k为根的子树的节点的最大值
每次查询最小的i 使得a[i]>=h (优先查左子树)
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define MEM(a,x) memset(a,x,sizeof(a))
using namespace std;
const int inf=1e9+7;
const int N = 5e4+5;
int a[N],b[N];
int rmq[4*N];
void add(int k,int l,int r,int pos,int x){//a[pos]+=x
if(l<=pos&&pos<=r){
if(l==r){
rmq[k]+=x;
}
else{
int mid=(l+r)/2;
add(2*k+1,l,mid,pos,x);
add(2*k+2,mid+1,r,pos,x);
rmq[k]=max(rmq[2*k+1],rmq[2*k+2]);
}
}
}
int query(int k,int l,int r,int h){
if(l==r){
return l;
}
int mid=(l+r)/2;
if(rmq[2*k+1]>=h){
return query(2*k+1,l,mid,h);
}
if(mid+1<=r){
return query(2*k+2,mid+1,r,h);
}
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
int n,m;
while(~scanf("%d%d",&m,&n)){
MEM(rmq,0);
for(int i=0;i<m;++i){
scanf("%d",&a[i]);
add(0,0,m-1,i,a[i]);
}
for(int i=0;i<n;++i){
int h;
scanf("%d",&h);
if(h<=a[0]||h>rmq[0]){
continue;
}
int idx=query(0,0,m-1,h);
a[idx-1]+=1;
add(0,0,m-1,idx-1,1);
}
for(int i=0;i<m;++i){
printf("%d\n",a[i]);
}
}
return 0;
}