【XSY2484】mex 离散化 线段树

题目大意

  给你一个无限长的数组,初始的时候都为 0 ,有3种操作:

  操作1是把给定区间 [l,r] 设为 1

  操作2是把给定区间 [l,r] 设为 0

  操作3把给定区间 [l,r]0,1 反转;

  一共 n 个操作,每次操作后要输出最小位置的0

   n100000,1lr1018

题解

  本题可以用平衡树做,这样就不用离散化了

  下面是线段树做法

  因为 l,r 很大,所以要离散化。通过证(guan)明(cha)发现,答案只可能是 1,l,r+1 。我们把这 2n+1 个点拿出来离散化,然后用线段树维护区间和就行了。我维护了最左边的 0 和最左边的1

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef int zjt_ak_noi_2018;
typedef long long ll;
typedef pair<zjt_ak_noi_2018,zjt_ak_noi_2018> pii;
struct node
{
    zjt_ak_noi_2018 l,r;
    zjt_ak_noi_2018 ls,rs;
    zjt_ak_noi_2018 s0,s1;
    zjt_ak_noi_2018 t1,t2;
    node()
    {
        ls=rs=0;
        s0=s1=0;
        t1=-1;
        t2=0;
    }
};
node a[500010];
zjt_ak_noi_2018 rt;
zjt_ak_noi_2018 cnt=0;
zjt_ak_noi_2018 merge(zjt_ak_noi_2018 v1,zjt_ak_noi_2018 v2)
{
    if(!v1||!v2)
        return v1+v2;
    return min(v1,v2);
}
void build(zjt_ak_noi_2018 &p,zjt_ak_noi_2018 l,zjt_ak_noi_2018 r)
{
    p=++cnt;
    a[p].l=l;
    a[p].r=r;
    if(l==r)
    {
        a[p].s0=l;
        return;
    }
    zjt_ak_noi_2018 mid=(l+r)>>1;
    build(a[p].ls,l,mid);
    build(a[p].rs,mid+1,r);
    a[p].s0=merge(a[a[p].ls].s0,a[a[p].rs].s0);
    a[p].s1=merge(a[a[p].rs].s1,a[a[p].rs].s1);
}
void fill(zjt_ak_noi_2018 p,zjt_ak_noi_2018 v)
{
    if(v)
    {
        a[p].s0=0;
        a[p].s1=a[p].l;
    }
    else
    {
        a[p].s0=a[p].l;
        a[p].s1=0;
    }
    a[p].t1=v;
    a[p].t2=0;
}
void reverse(zjt_ak_noi_2018 p)
{
    swap(a[p].s0,a[p].s1);
    a[p].t2^=1;
}
void push(zjt_ak_noi_2018 p)
{
    if(a[p].l!=a[p].r)
    {
        if(~a[p].t1)
        {
            fill(a[p].ls,a[p].t1);
            fill(a[p].rs,a[p].t1);
            a[p].t1=-1;
        }
        if(a[p].t2)
        {
            reverse(a[p].ls);
            reverse(a[p].rs);
            a[p].t2=0;
        }
    }
}
void fill(zjt_ak_noi_2018 p,zjt_ak_noi_2018 l,zjt_ak_noi_2018 r,zjt_ak_noi_2018 v)
{
    if(l<=a[p].l&&r>=a[p].r)
    {
        fill(p,v);
        return;
    }
    push(p);
    zjt_ak_noi_2018 mid=(a[p].l+a[p].r)>>1;
    if(l<=mid)
        fill(a[p].ls,l,r,v);
    if(r>mid)
        fill(a[p].rs,l,r,v);
    a[p].s0=merge(a[a[p].ls].s0,a[a[p].rs].s0);
    a[p].s1=merge(a[a[p].ls].s1,a[a[p].rs].s1);
}
void reverse(zjt_ak_noi_2018 p,zjt_ak_noi_2018 l,zjt_ak_noi_2018 r)
{
    if(l<=a[p].l&&r>=a[p].r)
    {
        reverse(p);
        return;
    }
    push(p);
    zjt_ak_noi_2018 mid=(a[p].l+a[p].r)>>1;
    if(l<=mid)
        reverse(a[p].ls,l,r);
    if(r>mid)
        reverse(a[p].rs,l,r);
    a[p].s0=merge(a[a[p].ls].s0,a[a[p].rs].s0);
    a[p].s1=merge(a[a[p].ls].s1,a[a[p].rs].s1);
}
//zjt_ak_noi_2018 query(zjt_ak_noi_2018 p,zjt_ak_noi_2018 l,zjt_ak_noi_2018 r)
//{
//  if(l<=a[p].l&&r>=a[p].r)
//      return a[p].s0;
//  push(p);
//  zjt_ak_noi_2018 mid=(a[p].l+a[p].r)>>1;
//  zjt_ak_noi_2018 s=0;
//  if(l<=mid)
//      s=merge(s,query(a[p].ls,l,r));
//  if(r>mid)
//      s=merge(s,query(a[p].rs,l,r));
//  return s;
//}
zjt_ak_noi_2018 op[100010];
ll l[100010];
ll r[100010];
ll d[200010];
zjt_ak_noi_2018 main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    zjt_ak_noi_2018 n,m=0;
    scanf("%d",&n);
    zjt_ak_noi_2018 i;
    for(i=1;i<=n;i++)
    {
        scanf("%d%lld%lld",&op[i],&l[i],&r[i]);
        d[++m]=l[i];
        d[++m]=r[i]+1;
    }
    d[++m]=1;
    sort(d+1,d+m+1);
    m=unique(d+1,d+m+1)-d-1;
    for(i=1;i<=n;i++)
    {
        l[i]=lower_bound(d+1,d+m+1,l[i])-d;
        r[i]=upper_bound(d+1,d+m+1,r[i])-d-1;
    }
    build(rt,1,m);
    for(i=1;i<=n;i++)
    {
        if(op[i]==1)
            fill(rt,l[i],r[i],1);
        else if(op[i]==2)
            fill(rt,l[i],r[i],0);
        else
            reverse(rt,l[i],r[i]);
        printf("%lld\n",d[a[rt].s0]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值