[Codeforces]817F. MEX Queries
You are given a set of integer numbers, initially it is empty. You should perform n queries. There are three different types of queries: 1 l r — Add all missing numbers from the interval [l, r] 2 l r — Remove all present numbers from the interval [l, r] 3 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: {3, 4} — the interval [3, 4] is added {1, 2, 5, 6} — numbers {3, 4} from the interval [1, 6] got deleted and all the others are added {5, 6} — numbers {1, 2} got deleted
题意
给你一个无限长的数组,初始的时候都为0,操作1是把给定区间清零,操作2是把给定区间设为1,操作3把给定区间反转。每次操作后要输出最小位置的0。
题解
看到数据范围n<=10^5,结合题意可以考虑使用线段树维护对区间的修改操作。但是l,r<=10^18,所以首先要离散化一下。在使用线段树维护的时候,节点维护该区间数相加的总和。对于操作1和操作2,我们分别赋值为1和0,对于操作3,我们把区间反转,那么新的区间和就是区间的长度减去原来的区间和。然后每次查询最小位置的0,只需要看一下左儿子所代表的区间是否小于这个区间的长度,如果是就在左儿子,否则就在右儿子查找。
题目细节
这道题有很多坑人的点,首先,在离散化的时候必须把1也加上,因为答案可能为1;线段树在下传标记时要注意顺序;记录原来信息的数组必须得开long long,空间一定要开够。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(register int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=
0,p=
1;
char ch=getchar();
while(!((
'0'<=ch && ch<=
'9') || ch==
'-'))ch=getchar();
if(ch==
'-')p=-
1,ch=getchar();
while(
'0'<=ch && ch<=
'9')sum=sum*
10+ch-
48,ch=getchar();
return sum*p;
}
const int maxn=
150020;
map <ll,int> mp;
int m,cnt;
ll s[maxn*
3],n;
struct qu {
ll l,r;
int type;
}a[maxn];
struct node {
int s,lz,id;
}c[maxn*
10];
#define lc (o<<1)
#define rc (o<<1 | 1)
#define left lc,l,mid
#define right rc,mid+1,r
inline void make_tree(
int o,
int l,
int r)
{
c[o].s=
0;c[o].lz=-
1;c[o].id=
0;
if(l==r)
return;
int mid=(l+r)>>
1;
make_tree(left);
make_tree(right);
}
void maintain(
int o,
int l,
int r)
{
c[o].s=c[lc].s+c[rc].s;
}
void pushdown(
int o,
int l,
int r)
{
int mid=(l+r)>>
1;
if(c[o].lz!=-
1)
{
c[lc].lz=c[rc].lz=c[o].lz;
c[lc].s=(mid-l+
1)*c[o].lz;
c[rc].s=(r-mid)*c[o].lz;
c[lc].id=c[rc].id=
0;
c[o].lz=-
1;
}
if(c[o].id)
{
c[lc].id^=
1;
c[rc].id^=
1;
c[lc].s=(mid-l+
1)-c[lc].s;
c[rc].s=(r-mid)-c[rc].s;
c[o].id=
0;
}
}
inline void updates(
int ql,
int qr,
int x,
int o,
int l,
int r)
{
pushdown(o,l,r);
if(ql==l && r==qr)
{
c[o].s=(r-l+
1)*x;
c[o].lz=x;
c[o].id=
0;
return;
}
int mid=(l+r)>>
1;
if(ql>mid)
{
updates(ql,qr,x,right);
}
else if(qr<=mid)
{
updates(ql,qr,x,left);
}
else
{
updates(ql,mid,x,left);
updates(mid+
1,qr,x,right);
}
maintain(o,l,r);
}
inline void updatex(
int ql,
int qr,
int o,
int l,
int r)
{
pushdown(o,l,r);
if(ql==l && r==qr)
{
c[o].s=(r-l+
1)-c[o].s;
c[o].id^=
1;
return;
}
int mid=(l+r)>>
1;
if(ql>mid)
{
updatex(ql,qr,right);
}
else if(qr<=mid)
{
updatex(ql,qr,left);
}
else
{
updatex(ql,mid,left);
updatex(mid+
1,qr,right);
}
maintain(o,l,r);
}
void init()
{
m=read();
REP(i,
1,m)
{
cin>>a[i].type>>a[i].l>>a[i].r;
a[i].r++;
s[++cnt]=a[i].l;
s[++cnt]=a[i].r;
}
s[++cnt]=
1;
sort(s+
1,s+cnt+
1);
n=unique(s+
1,s+cnt+
1)-(s+
1);
REP(i,
1,n)mp[s[i]]=i;
make_tree(
1,
1,n);
}
void query(
int o,
int l,
int r)
{
if(l==r)
{
cout<<s[l]<<endl;
return;
}
int mid=(l+r)>>
1;
pushdown(o,l,r);
if(c[lc].s<mid-l+
1)
query(left);
else query(right);
}
void doing()
{
REP(i,
1,m)
{
int type=a[i].type,l=mp[a[i].l],r=mp[a[i].r]-
1;
if(type==
1)
{
updates(l,r,
1,
1,
1,n);
}
else if(type==
2)
{
updates(l,r,
0,
1,
1,n);
}
else
{
updatex(l,r,
1,
1,n);
}
query(
1,
1,n);
}
}
int main()
{
init();
doing();
return 0;
}