CodeForces1326 E. Bombs (线段树)

E. Bombs

You are given a permutation, p1,p2,…,pn.

Imagine that some positions of the permutation contain bombs, such that there exists at least one position without a bomb.

For some fixed configuration of bombs, consider the following process. Initially, there is an empty set, A.

For each i from 1 to n:

  • Add pi to A.
  • If the i-th position contains a bomb, remove the largest element in A.

After the process is completed, A will be non-empty. The cost of the configuration of bombs equals the largest element in A.

You are given another permutation, q1,q2,…,qn.

For each 1≤i≤n, find the cost of a configuration of bombs such that there exists a bomb in positions q1,q2,…,qi−1.

For example, for i=1, you need to find the cost of a configuration without bombs, and for i=n, you need to find the cost of a configuration with bombs in positions q1,q2,…,qn−1.

Input

The first line contains a single integer, n (2≤n≤300000).

The second line contains n distinct integers p1,p2,…,pn (1≤pi≤n).

The third line contains n distinct integers q1,q2,…,qn (1≤qi≤n).

Output

Print n space-separated integers, such that the i-th of them equals the cost of a configuration of bombs in positions q1,q2,…,qi−1.

Examples
input

3
3 2 1
1 2 3

output

3 2 1

input

6
2 3 6 1 5 4
5 2 1 4 6 3

output

6 5 5 5 4 1


解法:

因为答案是非递增的,因此可以把问题转化为判断答案是否为某个数x,不断检查是否合法
假设答案为x,那么序列中每个至少存在一个>=x的数未被炸掉
某个位置需要被炸掉,那么这个位置开始的右边需要有一个炸弹
假设从右边起第k个>=x的位置为pos,那么pos位置向右至少要有k个炸掉

用线段树维护序列b,b(i)表示i位置向右的>=x的数的数量减去炸弹的数量,
如果所有的b(i)<=0,表明>=x的数都被炸没了,那么令x–继续判断直到当存在b(i)>0时x就是当前答案
需要用到区间加法和区间最值。

从判断x转化为到判断x-1的过程中很好维护,因为>=x的一定是>=x-1的。

code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=3e5+5;
int p[maxm],q[maxm],n;
int pos[maxm];
struct ST{
    int lz[maxm<<2];
    int a[maxm<<2];
    void pushup(int node){
        a[node]=max(a[node*2],a[node*2+1]);
    }
    void pushdown(int node){
        if(lz[node]){
            lz[node*2]+=lz[node];
            lz[node*2+1]+=lz[node];
            a[node*2]+=lz[node];
            a[node*2+1]+=lz[node];
            lz[node]=0;
        }
    }
    void update(int st,int ed,int val,int l,int r,int node){
        if(st<=l&&ed>=r){
            a[node]+=val;
            lz[node]+=val;
            return ;
        }
        pushdown(node);
        int mid=(l+r)/2;
        if(st<=mid)update(st,ed,val,l,mid,node*2);
        if(ed>mid)update(st,ed,val,mid+1,r,node*2+1);
        pushup(node);
    }
    int ask(int st,int ed,int l,int r,int node){
        if(st<=l&&ed>=r)return a[node];
        pushdown(node);
        int mid=(l+r)/2;
        int ans=-1e9;
        if(st<=mid)ans=max(ans,ask(st,ed,l,mid,node*2));
        if(ed>mid)ans=max(ans,ask(st,ed,mid+1,r,node*2+1));
        return ans;
    }
}T;
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&p[i]),pos[p[i]]=i;
    for(int i=1;i<=n;i++)scanf("%d",&q[i]);
    int x=n;
    T.update(1,pos[n],1,1,n,1);
    for(int i=1;i<=n;i++){
        printf("%d ",x);
        T.update(1,q[i],-1,1,n,1);
        while(x>=1&&T.ask(1,n,1,n,1)<=0){
            x--;
            T.update(1,pos[x],1,1,n,1);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值