码迷,mamicode.com
首页 > 其他好文 > 详细

Bombs CodeForces - 1326E 线段树

时间:2020-03-21 18:20:11      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:节点   mod   pair   name   pac   long   上传   push   变化   

一开始输出的必定为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;
}

Bombs CodeForces - 1326E 线段树

标签:节点   mod   pair   name   pac   long   上传   push   变化   

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12540242.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!