题目链接
思路:显然答案是单调不增的。
根据这个性质,我们可以枚举答案来检查答案是否合法。
假设第 i 1 i-1 i1次的答案为 x x x,此时我们在 q i q_i qi位置新加入了一个炸弹,那么当前存在炸弹的位置就是 q 1 , q 2 . . . . . q i q_1,q_2.....q_i q1,q2.....qi
如果存在一个位置 y y y,使得 [ y , n ] [y,n] [y,n] x \geq x x p i p_i pi的个数大于 [ y , n ] [y,n] [y,n]上炸弹的个数,那么此时的答案 x x x就是合法的。
那么我们维护一个 b b b数组, b i = [ i , n ] b_i=[i,n] bi=[i,n]上大于等于 x x x的数的个数 [ i , n ] -[i,n] [i,n]上炸弹的个数。
当前仅当 b b b的最大值>0时, x x x才合法。
否则,我们把 x x x变小,再更新 b b b数组进行判断即可。
细节见代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mid (l+r>>1)
#define ls o<<1
#define rs o<<1|1
int n,a[N],b[N],pos[N];
int t[N<<2],lz[N<<2];
void pd(int o){
  if(lz[o]){
    lz[ls]+=lz[o];
    lz[rs]+=lz[o];
    t[ls]+=lz[o];
    t[rs]+=lz[o];
    lz[o]=0;
  }
}
void up(int o,int l,int r,int x,int y,int d){
  if(l>=x&&r<=y){
    t[o]+=d;
    lz[o]+=d;
    return ;
  }
  pd(o);
  if(x<=mid)up(ls,l,mid,x,y,d);
  if(y>mid)up(rs,mid+1,r,x,y,d);
  t[o]=max(t[ls],t[rs]);
}
int ge(int o,int l,int r,int x,int y){
  if(l>=x&&r<=y){
    return t[o];
  }
  pd(o);
  int ans=-1e9;
  if(x<=mid)ans=max(ans,ge(ls,l,mid,x,y));
  if(y>mid)ans=max(ans,ge(rs,mid+1,r,x,y));
  return ans;
}
int po=1e9,ans;
int ge(){
  if(t[1]>0)return 1;//合法
  ans--;
  up(1,1,n,1,pos[ans],1);//不合法我们更新
  return 0;
}
int main(){
  ios::sync_with_stdio(false);
  cin>>n;ans=n;
  for(int i=1;i<=n;i++)cin>>a[i],pos[a[i]]=i;
  for(int i=1;i<=n;i++)cin>>b[i];
  cout<<n<<' ';up(1,1,n,1,pos[n],1);//第一次的答案肯定是n
  for(int i=1;i<n;i++){
    up(1,1,n,1,b[i],-1);//新加入一个炸弹
    while(!ge());
    cout<<ans<<' ';
  }
  return 0;
}