一个长度为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 首先考虑n平方肯定爆的,所以开一个数组zhiyin[]保存后面大于它的第一个点,如果大于这个点就直接根据数组保存的坐标访问
2 要注意的是高度变化,zhiyin数组就要更新或者处理(都可以)处理可以是while语句判断前推,
3 如果是最大zhiyin应保存为0,若大于该点高度,且判断为0,直接break,因为后面没有点比他高了,直接跳过
附上代码:
#include<iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <stack>
#include<cstdio>
#include <set>
using namespace std;
int main()
{
long long int numd,nump,di[50000],temp,temp1,zhiyin[50000],pao,low,high,i,j;
scanf("%lld%lld",&numd,&nump);
memset(zhiyin,0,sizeof(zhiyin));
for(i=0;i<numd;i++)
scanf("%lld",&di[i]);
for(i=1;i<numd;i++) //规定0
{
if(di[i]>di[0])
{
zhiyin[0]=i;
break;
}
}
temp=numd-1;
for(i=1;i<temp;i++) //初使化zhiyin
{
if(di[i]>di[i-1]) //增长纠正
{
low=zhiyin[i-1];
while(di[low]<=di[low-1])
low--;
}
else
low=i+1;
for(;low<numd;low++)
if(di[low]>di[i])
{
zhiyin[i]=low;
break;
}
}
while(nump--) //发炮
{
scanf("%lld",&pao);
for(i=0;i<numd;)
{
if(pao>di[i])
{
if(zhiyin[i]==0)
break;
while(di[zhiyin[i]]<=di[zhiyin[i]-1]) //jiu zheng
{
zhiyin[i]--;
}
while(di[zhiyin[i]]>di[i])
zhiyin[i]--;
zhiyin[i]++;
i=zhiyin[i]-1;
}
else if(i!=0) //di yu
{
di[i-1]++;
break;
}
else
break;
i++;
}
}
for(i=0;i<numd;i++)
printf("%lld\n",di[i]);
return 0;
}
然后我想试试盘子方法,结合二分会不会更快
1 :用ma数组保存从0到i 的最高值ma[i],ma[0]就是他本身高度
2 :二分搜索点mid ,在点mid+1的ma高度大于等于炮弹,且ma高度小于炮弹高度的点,也就是ma值的增高点
附上代码:
#include<iostream>
#include<cstdio>
using namespace std;
int numd,nump,di[50000],temp,ma[50000],pao,low,high,i,mid;
int main()
{
scanf("%d%d",&numd,&nump);
scanf("%d",&di[0]);
ma[0]=di[0];
for(i=1;i<numd;i++)
{
scanf("%d",&di[i]);
if(di[i]>ma[i-1])
ma[i]=di[i];
else
ma[i]=ma[i-1];
}
while(nump--) //发炮
{
scanf("%d",&pao);
if(pao<=di[0])
continue;
low=0;
high=numd-1;
temp=-1;
while(low<=high)
{
mid=(low+high)/2;
if(ma[mid]>=pao)
{
if(ma[mid-1]<pao)
{
temp=mid-1;
break;
}
else
high=mid-1;;
}
if(ma[mid]<pao)
{
if(ma[mid+1]>=pao)
{
temp=mid;
break;
}
else
low=mid+1;
}
}
if(temp==-1)
continue;
di[temp]++;
if(ma[temp]<di[temp])
{
ma[temp]=di[temp];
}
}
for(i=0;i<numd;i++)
printf("%d\n",di[i]);
return 0;
}