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;
}
原文地址:https://www.cnblogs.com/jhz033/p/7079334.html