Bombs CodeForces - 1326E 线段树
一开始输出的必定为n,初始时,1~pos[n]都+1,只要tr[1].v>0,那么就说明,不存在位置大于等于pos[k]的炸弹
然后依次进行修改,处理1~q[n],如果tr[1].v<=0,那么就说明,有炸弹的位置大于等于pos[k]
然后k--,再次进行上述操作
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef long long LL;
const int N = 3e5 + 5;
int n;
int p[N], q[N], pos[N];
int maxv[N << 2], lz[N << 2];
struct Node
{
int l, r;
LL v;
LL add;
}tr[N * 4];
//用子节点的信息来计算父节点的信息
void pushup(int u)
{
tr[u].v = max(tr[u << 1].v , tr[u << 1 | 1].v);
}
void pushdown(int u)
{
auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
if (root.add)
{
left.add += root.add;
left.v += root.add;
right.add += root.add;
right.v += root.add;
root.add = 0;
}
}
void build(int u, int l, int r)
{
if (l == r)
tr[u] = {l, r, 0, 0};
else
{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r, int d)
{
if (tr[u].l >= l && tr[u].r <= r)
{
//总和
tr[u].v += d;
//懒标记
tr[u].add += d;
}
// 区间太大,一定要分裂
else
{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid)
modify(u << 1, l, r, d);
if (r > mid)
modify(u << 1 | 1, l, r, d);
//当前区间和发生变化,需要向上传
pushup(u);
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>p[i],pos[p[i]]=i;
for(int i=1;i<=n;i++)
cin>>q[i];
int k=n;
//开始一个炸弹都没有
//直接输出
cout<<k<<" ";
build(1,1,n);
//0~最大的数所在位置都+1
modify(1,1,pos[k],1);
for(int i=1;i<n;i++)
{
//区间修改
modify(1,1,q[i],-1);
while(1)
{
//查询区间最大值
int maxv=tr[1].v;
//如果<=0,那么也就说明上面的修改中
//必有q[i]>=pos[k]
//也就是说,必定会去除最大值
//那么当前最大值也就不适用
if(maxv<=0)
//最大值--
//并把前面的区间都+1
//如果此时还是<=0
//说明前面的修改,已经将当前数值去除
modify(1,1,pos[--k],1);
else
break;
}
cout<<k<<" ";
}
}
int main()
{
solve();
return 0;
}