一,思路:
1.这是一个模拟链表题,考察对链表的掌握和熟悉程度。在这这题当中有个坑点就是,当一个怪在这回合死了,他任然可以旁边的怪照成伤害(不能着急的给他删掉,不然会出问题)。
2.还有这题很容易就想到,暴力模拟但是时间复杂度:n^2级别是过不了的。所以要优化,找到循环当中那些步骤是冗余的。显然我们可以发现,当一只怪的在这回合没有死掉,且他左右两边的怪也没有死掉,那么下回合他肯定不会死掉。利用这个特点,我们可以用set记录每回合后,那些怪物可能会死掉。
二,代码:
#include <iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int N=3e5+10;
int ne[N],pre[N];
int arr[N],brr[N];
//记录标记那些怪已近死掉
bool st[N];
void Solved() {
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>arr[i];
for(int i=1;i<=n;i++) cin>>brr[i];
set<int> s;
//当有多组输入时,预处理处理边界情况,会让后面代码很好写,可以不用特判了
arr[n+1]=0;
st[n+1]=false;
for(int i=1;i<=n;i++){
//数组模拟链表
pre[i]=i-1;
ne[i]=i+1;
//刚开始所有怪物都可能死掉
s.insert(i);
//刚开始所有怪物都存活
st[i]=true;
}
for(int i=1;i<=n;i++){
//将这回合已近死了的怪物,存起来不要马上删掉
set<int> temp;
int cnt=0;
//判断那些怪物已经死掉了,并标记
for(auto t: s){
if(arr[pre[t]]+arr[ne[t]]>brr[t]){
temp.insert(t);
st[t]=false;
}
}
s.clear();
//处理删除操作,把下回合可能死掉的怪物存起来
for(auto t:temp){
cnt++;
//假如怪物在这回合已经死了的话,就不要等到下一回合了
if(st[pre[t]]) s.insert(pre[t]);
if(st[ne[t]]) s.insert(ne[t]);
//链表删除操作
pre[ne[t]]=pre[t];
ne[pre[t]]=ne[t];
}
cout<<cnt<<" ";
}
cout<<endl;
}
int main()
{
int t;
cin>>t;
while(t--) {
Solved();
}
return 0;
}