1287 加农炮(传送门)
题意
中文不解释
解题思路
看完这道题目最暴力的方法和思路,就是寻找从左到右第一个大于等于指定子弹高度的地形高度,时间复杂度 O(n2) 。
接下来优化就是针对区间了,打个比方如果Max[i]
表示
[1,i]
这个区间的最大值,那么我们针对一个子弹高度h
要处理的就是最靠近左边的h <= Max[i]
,那么子弹落下的位置为i - 1
。
也就是我们最终的目标是找寻满足h <= Max[i]
的最小左下标,如果是这样的话,我们可以用线段树,RMQ这些来实时更新区间最大值Max
,然后来得到最小左下标。
代码
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <algorithm>
#define lson l, mid, rt << 1
#define rson mid + 1,r , rt << 1| 1
#define FIN freopen("input.txt", "r", stdin)
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 5;
int Max[MAXN << 2];
int Vax[MAXN << 2], plen;
void push_up(int rt){
Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void build(int l, int r, int rt){
if(l == r){
scanf("%d", &Max[rt]);
Vax[plen ++] = Max[rt];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void update(int p, int l, int r, int rt){
if(l == r){
Max[rt] ++;
Vax[p] ++;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) update(p, lson);
else update(p, rson);
push_up(rt);
}
int get_pos(int pv, int l, int r, int rt){
if(l == r){
int p = (pv <= Max[rt] ? l - 1 : l);
return p;
}
int mid = (l + r) >> 1;
if(pv <= Max[rt << 1]) return get_pos(pv, lson);
else return get_pos(pv, rson);
}
int m, n;
int main(){
//FIN;
while(~scanf("%d%d", &n, &m)){
int x;
plen = 1;
build(1, n, 1);
while(m --){
scanf("%d", &x);
if(x <= Vax[1] || x > Max[1]) continue;
int p = get_pos(x, 1, n, 1);
update(p, 1, n, 1);
}
for(int i = 1;i < plen;i ++){
printf("%d\n", Vax[i]);
}
}
return 0;
}