• Educational Codeforces Round 23 F. MEX Queries 离散化+线段树


    F. MEX Queries
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    You are given a set of integer numbers, initially it is empty. You should perform n queries.

    There are three different types of queries:

    • l r — Add all missing numbers from the interval [l, r]
    • l r — Remove all present numbers from the interval [l, r]
    • l r — Invert the interval [l, r] — add all missing and remove all present numbers from the interval [l, r]

    After each query you should output MEX of the set — the smallest positive (MEX  ≥ 1) integer number which is not presented in the set.

    Input

    The first line contains one integer number n (1 ≤ n ≤ 105).

    Next n lines contain three integer numbers t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 1018) — type of the query, left and right bounds.

    Output

    Print MEX of the set after each query.

    Examples
    input
    3
    1 3 4
    3 1 6
    2 1 3
    output
    1
    3
    1
    input
    4
    1 1 3
    3 5 6
    2 4 4
    3 1 6
    output
    4
    4
    4
    1
    Note

    Here are contents of the set after each query in the first example:

    1. {3, 4} — the interval [3, 4] is added
    2. {1, 2, 5, 6} — numbers {3, 4} from the interval [1, 6] got deleted and all the others are added
    3. {5, 6} — numbers {1, 2} got deleted

    题意:给你n个区间,1操作表示把[l,r]赋值为1,2操作表示把[l,r]赋值为0,3操作表示把[l,r]异或1;

         求第一个不为0的正整数。

    思路:对于所有区间[l,r]取出l,r,r+1三个点;

       离散化放入线段树中去

       现在需要区间修改,区间异或,查询

       需要两个lazy标记,一个存修改的值,一个存是否异或1.

       区间查询log查找即可,详见代码。

       小trick:需要加入最小值,即是1的情况;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    #include<bitset>
    #include<time.h>
    using namespace std;
    #define LL long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=3e5+10,M=4e6+10,inf=2147483647,mod=1e9+7;
    const LL INF=1e18+10,MOD=1e9+7;
    
    int L=3e5+10;
    struct LT
    {
        int sum[N<<2],to[N<<2],sw[N<<2];
        void pushdown(int pos,int l,int r)
        {
            int mid=(l+r)>>1;
            if(to[pos]!=-1)
            {
                to[pos<<1]=to[pos];
                to[pos<<1|1]=to[pos];
                sum[pos<<1]=to[pos]*(mid-l+1);
                sum[pos<<1|1]=to[pos]*(r-mid);
                to[pos]=-1;
                sw[pos]=0;
            }
            if(sw[pos])
            {
                if(to[pos<<1]!=-1)to[pos<<1]=!to[pos<<1];
                else sw[pos<<1]=!sw[pos<<1];
                if(to[pos<<1|1]!=-1)to[pos<<1|1]=!to[pos<<1|1];
                else sw[pos<<1|1]=!sw[pos<<1|1];
                sum[pos<<1]=(mid-l+1)-sum[pos<<1];
                sum[pos<<1|1]=(r-mid)-sum[pos<<1|1];
                sw[pos]=0;
            }
        }
        void build(int l,int r,int pos)
        {
            to[pos]=-1;
            sw[pos]=0;
            sum[pos]=0;
            if(l==r)return;
            int mid=(l+r)>>1;
            build(l,mid,pos<<1);
            build(mid+1,r,pos<<1|1);
        }
        void update(int L,int R,int c,int l,int r,int pos)
        {
            if(L<=l&&r<=R)
            {
                if(c==2)
                {
                    if(to[pos]!=-1)to[pos]=!to[pos];
                    else sw[pos]=!sw[pos];
                }
                else
                {
                    to[pos]=c;
                    sw[pos]=0;
                }
                if(c==2)sum[pos]=r-l+1-sum[pos];
                else sum[pos]=(r-l+1)*c;
                return;
            }
            pushdown(pos,l,r);
            int mid=(l+r)>>1;
            if(L<=mid)update(L,R,c,l,mid,pos<<1);
            if(R>mid) update(L,R,c,mid+1,r,pos<<1|1);
            sum[pos]=sum[pos<<1|1]+sum[pos<<1];
        }
        int query(int l,int r,int pos)
        {
            //cout<<l<<" "<<r<<" "<<sum[pos]<<" "<<to[pos]<<endl;
            if(l==r)return l;
            pushdown(pos,l,r);
            //cout<<sum[pos<<1]<<" "<<sum[pos<<1|1]<<endl;
            int mid=(l+r)>>1;
            if(sum[pos<<1]==mid-l+1)return query(mid+1,r,pos<<1|1);
            else return query(l,mid,pos<<1);
        }
    }tree;
    
    int t[N],len;
    LL l[N],r[N],s[N];
    int getpos(LL x)
    {
        int pos=lower_bound(s+1,s+len,x)-s;
        return pos;
    }
    int main()
    {
        int n,k=0;
        scanf("%d",&n);
        s[++k]=1;
        for(int i=1;i<=n;i++)
            scanf("%d%lld%lld",&t[i],&l[i],&r[i]),s[++k]=l[i],s[++k]=r[i],s[++k]=r[i]+1;
        sort(s+1,s+1+k);
        len=unique(s+1,s+1+k)-s;
        tree.build(1,L,1);
        for(int i=1;i<=n;i++)
        {
            int z=getpos(l[i]),y=getpos(r[i]);
            if(t[i]==1)tree.update(z,y,1,1,L,1);
            else if(t[i]==2)tree.update(z,y,0,1,L,1);
            else if(t[i]==3)tree.update(z,y,2,1,L,1);
            int x=tree.query(1,L,1);
            //cout<<"xxx "<<x<<" "<<tree.sum[1]<<endl;
            printf("%lld
    ",s[x]);
        }
        return 0;
    }
  • 相关阅读:
    【转】跨域的理解与实现
    【3.5】从今天开始学习WCF技术
    LAB.js使用
    资源文件的动态加载
    C#对图片文件的压缩、裁剪操作初探
    WCF技术剖析_学习笔记之一
    SQL 写入调优
    【转】Nosql,为什么要使用
    wcf配置文件
    wcf错误
  • 原文地址:https://www.cnblogs.com/jhz033/p/7079334.html
Copyright © 2020-2023  润新知