Educational Codeforces Round 23F

http://codeforces.com/contest/817/problem/F

无限长的数组,刚开始每一位是0,三种操作,1,把(l,r)之间不是1的变成1,2,把(l,r)之间不是0的变成0,3,把0变成1,1变成0,每次操作都要查询该数组的mex(最小的没有在集合中出现的数)

解法:很明显的线段树,lazy标记有3个,分别代表3中操作的,当pushdown的时候如果lazy为1或2都直接下传,但是当lazy是3的时候,不能直接下传,因为1,2操作优先级更大,所以pushdown时特判一下这种情况即可(当儿子的lazy为1时,刚好需要先全变1然后翻转就是2操作1了,lazy为2同理,lazy为3的话直接翻转两次等同于没有翻转),查询的话,直接查询左右区间,如果左区间是满的,那么右边,否则查询左侧,注意hash的时候把1加上去,每个点左右两个点也要加进去,不然会出现断层!!

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-9;
const int N=1200000+10,maxn=100000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

struct qu{
    int t;
    ll l,r;
}q[N];
int lazy[N<<2],value[N<<2];
int cnt;
ll Hash[N<<2];
void pushup(int rt)
{
    value[rt]=value[rt<<1]+value[rt<<1|1];
}
void pushdown(int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(lazy[rt]==1)
    {
        value[rt<<1]=m-l+1;
        value[rt<<1|1]=r-m;
        lazy[rt<<1]=lazy[rt<<1|1]=1;
    }
    else if(lazy[rt]==2)
    {
        value[rt<<1]=value[rt<<1|1]=0;
        lazy[rt<<1]=lazy[rt<<1|1]=2;
    }
    else if(lazy[rt]==3)
    {
        value[rt<<1]=m-l+1-value[rt<<1];
        value[rt<<1|1]=r-m-value[rt<<1|1];
        lazy[rt<<1]=3-lazy[rt<<1];
        lazy[rt<<1|1]=3-lazy[rt<<1|1];
    }
    lazy[rt]=0;
}
void build(int l,int r,int rt)
{
    value[rt]=0,lazy[rt]=0;
    if(l==r)return ;
    int m=(l+r)>>1;
    build(ls);build(rs);
}
void update(int L,int R,int op,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        if(op==1)
        {
            value[rt]=r-l+1;
            lazy[rt]=op;
        }
        else if(op==2)
        {
            value[rt]=0;
            lazy[rt]=op;
        }
        else
        {
            if(lazy[rt])pushdown(l,r,rt);
            value[rt]=r-l+1-value[rt];
            lazy[rt]=op;
        }
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,op,ls);
    if(m<R)update(L,R,op,rs);
    pushup(rt);
}
int query(int l,int r,int rt)
{
    if(l==r)return l;
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(value[rt<<1]==m-l+1)return query(rs);
    else return query(ls);
}
void add(ll x)
{
    if(x!=0)Hash[cnt++]=x;
}
int main()
{
    int n;
    cnt=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%lld%lld",&q[i].t,&q[i].l,&q[i].r);
        add(q[i].l-1),add(q[i].l),add(q[i].l+1);
        add(q[i].r-1),add(q[i].r),add(q[i].r+1);
    }
    Hash[cnt++]=1;
    sort(Hash,Hash+cnt);
    cnt=unique(Hash,Hash+cnt)-Hash;
//    for(int i=0;i<cnt;i++)printf("%lld ",Hash[i]);
//    puts("");
    build(1,cnt,1);
    for(int i=0;i<n;i++)
    {
        int op=q[i].t;
        int tel=lower_bound(Hash,Hash+cnt,q[i].l)-Hash;
        int ter=lower_bound(Hash,Hash+cnt,q[i].r)-Hash;
        update(tel+1,ter+1,q[i].t,1,cnt,1);
        int ans=query(1,cnt,1);
//        printf("%d %d %d
",tel,ter,ans);
        printf("%lld
",Hash[ans-1]);
    }
    return 0;
}
/********************
1
2 854690110384167294 954215012997404774
********************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/8511753.html