1287 加农炮
一个长度为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
思路:我们用线段树,如果该区间有比炮弹高度大的,那么我们先去看左区间最大值,没有再去右区间
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,m; 5 int a[50004],x; 6 int b[50004]; 7 8 struct node{ 9 int l,r,mx; 10 }c[50004*4]; 11 12 void build(int x,int L,int R){ 13 c[x].l=L; 14 c[x].r=R; 15 int mid=(L+R)>>1; 16 if(L==R){ 17 c[x].mx=a[L];return ; 18 } 19 build(2*x,L,mid);build(2*x+1,mid+1,R); 20 c[x].mx=max(c[2*x].mx,c[2*x+1].mx); 21 } 22 23 int query(int x,int xx){ 24 if(c[x].l==c[x].r){ 25 if(c[x].mx>=xx) return c[x].l-1; 26 } 27 // cout<<c[2*x].mx<<" "<<c[2*x+1].mx<<endl; 28 if(c[2*x].mx>=xx) query(2*x,xx); 29 else if(c[2*x+1].mx>=xx) query(2*x+1,xx); 30 else return 0; 31 } 32 33 void update(int x,int xx){ 34 if(c[x].l==xx&&c[x].r==xx){ 35 36 c[x].mx++;return ; 37 } 38 int mid=(c[x].l+c[x].r)>>1; 39 40 if(xx<=mid) update(2*x,xx); 41 else update(2*x+1,xx); 42 c[x].mx=max(c[2*x].mx,c[2*x+1].mx); 43 } 44 45 void hh(int x){ 46 if(c[x].l==c[x].r){ 47 b[c[x].l]=c[x].mx;return ; 48 } 49 hh(x*2);hh(2*x+1); 50 } 51 int main(){ 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 54 build(1,1,n); 55 for(int i=1;i<=m;i++){ 56 scanf("%d",&x); 57 int y=query(1,x); 58 59 if(y!=0) 60 update(1,y); 61 } 62 hh(1); 63 for(int i=1;i<=n;i++) printf("%d\n",b[i]); 64 }