51nod 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
思路:线段树+二分,利用线段树存储每一个区间内的山峰最高值,通过二分查找找出高度大于等于当前炮弹的山峰下标k,将k-1位置的山峰高度+1即可
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 6 using namespace std; 7 //typedef long long LL; 8 const int maxn = 50005; 9 int a[maxn],rs[maxn<<2]; 10 int n,m; 11 void pushup(int rt){ 12 rs[rt] = max(rs[rt<<1],rs[rt<<1|1]); 13 } 14 void build(int l,int r,int rt) 15 { 16 if(l==r){ 17 rs[rt] = a[l]; 18 return; 19 } 20 int mid=(l+r)>>1; 21 build(l,mid,rt<<1); 22 build(mid+1,r,rt<<1|1); 23 pushup(rt); 24 } 25 void update(int x,int l,int r,int rt) 26 { 27 if(l==r){ 28 rs[rt]++; 29 return; 30 } 31 int mid=(l+r)>>1; 32 if(x<=mid) update(x,l,mid,rt<<1); 33 else update(x,mid+1,r,rt<<1|1); 34 pushup(rt); 35 } 36 int query(int x,int l,int r,int rt)//根据x的值找出从左往右找出第一个能碰到的山峰的下标 37 { 38 if(l==r) return l; 39 int mid = (l+r)>>1; 40 if(x<=rs[rt<<1]) query(x,l,mid,rt<<1); 41 else query(x,mid+1,r,rt<<1|1); 42 } 43 int Query(int x,int l,int r,int rt)//根据点查询数据 44 { 45 if(l==r)return rs[rt]; 46 int mid = (l+r)>>1; 47 if(x<=mid)Query(x,l,mid,rt<<1); 48 else Query(x,mid+1,r,rt<<1|1); 49 } 50 int main() 51 { 52 ios::sync_with_stdio(false); 53 // freopen("in.txt","r",stdin); 54 while(cin>>n>>m){ 55 int x; 56 memset(rs,0,sizeof(rs)); 57 for(int i=1;i<=n;i++) 58 cin>>a[i]; 59 build(1,n,1); 60 for(int i=1;i<=m;i++){ 61 cin>>x; 62 // if(x>rs[1]||x<=a[1])continue;一开始在这里卡了好久 后头想起来第一个位置的高度可能也会更新所以每一次都需要查询 63 if(x>rs[1]||x<=Query(1,1,n,1))continue; 64 int k=query(x,1,n,1); 65 update(k-1,1,n,1);//更新前一个点的高度 66 } 67 for(int i=1;i<=n;i++) 68 cout<<Query(i,1,n,1)<<endl; 69 } 70 return 0; 71 }