51nod1287加农炮线段树找大于等于某个数的第一个值

一个长度为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}。

 收起

输入

第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)。

输出

输出共M行,每行一个数,对应最终的地形高度。

输入样例

9 11
1
2
0
4
3
2
1
5
7
2
8
0
7
6
5
3
4
5
6
5

输出样例

2
2
2
4
3
3
5
6
7

线段树维护区间最大值,每次输入一个炮弹,找到大于等于这个炮弹高度的第一个位置,把这个位置的地形高度加1,更新区间最大值

#include
#include
#include
#define lson 2*i,l,m
#define rson 2*i+1,m+1,r
#define maxn 50005
using namespace std;
int n,m;
int a[maxn];
int b[maxn];

int maxx[maxn*4];
void pushup(int i)
{
    maxx[i]=max(maxx[i*2],maxx[i*2+1]);
}
void build(int i,int l,int r)
{
    if(l==r)
    {
        maxx[i]=a[l];

        return;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(i);

}
int query(int p,int i,int l,int r)
{
    if(l==r)
        return l;
    int m=(l+r)/2;
    int res;
    if(p<=maxx[i*2])
        res=query(p,lson);
    else
        res=query(p,rson);
}
void update(int id,int val,int i,int l,int r)
{
    if(l==r)
    {

      maxx[i]=val;
      return;
    }
    int m=(l+r)/2;
    if(id<=m)
        update(id,val,lson);
    else
        update(id,val,rson);
        pushup(i);
}
int main()
{
    scanf("%d%d",&m,&n);

        for(int i=1;i<=m;i++)
            scanf("%d",&a[i]);
            build(1,1,m);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&b[i]);
                if(b[i]<=a[1]||b[i]>maxx[1])
                    continue;
                int pos=query(b[i],1,1,m);
                a[pos-1]++;
                update(pos-1,a[pos-1],1,1,m);
            }
            for(int i=1;i<=m;i++)
                printf("%d\n",a[i]);
             
            return 0;
    }

 

你可能感兴趣的:(线段树)