当前位置: 代码迷 >> 综合 >> 51NOD 1287 加农炮 线段树修改查询函数
  详细解决方案

51NOD 1287 加农炮 线段树修改查询函数

热度:13   发布时间:2024-01-15 06:23:22.0

1287 加农炮

  1. 1.0 秒
  2.  
  3. 131,072.0 KB
  4.  
  5. 20 分
  6.  
  7. 3级题

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

 

这题直接暴力就能过,但搜到一解法是修改线段树,让我很感兴趣,线段树已经维护的是最大值,但查询里面做了手脚,实现了找到最左边第一个>=他的数。

46ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define lson i<<1
#define rson i<<1|1
#define LS l,mid,lson
#define RS mid+1,r,rson
#define ll long long
#define N 100005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define EXP 1e-8
#define lowbit(x) (x&-x)int a[N],b[N];
int ans_max;
//注意一定要找一个临时变量记录下ans_***的答案,不然会覆盖
struct node
{int l,r;int maxx;
}tree[N<<2];
void pushup(int i)
{tree[i].maxx=max(tree[lson].maxx,tree[rson].maxx);
}//建立线段树
void build(int l,int r,int i)
{tree[i].l = l;tree[i].r = r;if(l == r){tree[i].maxx =a[l];return;}int mid = (l+r)>>1;build(LS);build(RS);pushup(i);
}
//tree[l,r]都变为val
void set_data(int l,int r,int i,int val)
{if(tree[i].l>=l&&tree[i].r<=r){tree[i].maxx = val;return;}int mid = (tree[i].l+tree[i].r)>>1;if(l<=mid)set_data(l,r,lson,val);if(r>mid)set_data(l,r,rson,val);pushup(i);
}
int query(int l,int r,int i,int val)
{//cout<<tree[i].l<<" "<<tree[i].r<<" "<<i<<endl;if(tree[i].l==tree[i].r){return tree[i].l;}int mid = (tree[i].l+tree[i].r)>>1;if(tree[lson].maxx>=val)return query(l,r,lson,val);elsereturn query(l,r,rson,val);pushup(i);
}int main()
{int n,m;scanf("%d%d",&n,&m);int maxx=0;for(int i=1; i<=n; i++){scanf("%d",&a[i]);maxx=max(maxx,a[i]);}build(1,n,1);for(int i=1; i<=m; i++){scanf("%d",&b[i]);if(b[i]>maxx||b[i]<=a[1]){continue;}// cout<<"*"<<b[i]<<endl;int pos=query(1,n,1,b[i]);a[pos-1]++;set_data(pos-1,pos-1,1,a[pos-1]);}for(int i=1; i<=n; i++){printf("%d\n",a[i]);}return 0;
}

暴力

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N=200000+7;
int a[N],b[N];
int main()
{int n,m;scanf("%d%d",&n,&m);int maxx=0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);maxx=max(maxx,a[i]);}for(int i=1;i<=m;i++){scanf("%d",&b[i]);if(b[i]>maxx||b[i]<=a[1]){continue;}for(int j=2;j<=n;j++){if(b[i]<=a[j]){a[j-1]++;break;}}}for(int i=1;i<=n;i++){printf("%d\n",a[i]);}return 0 ;
}