codeforces CF817F MEX Queries 线段树 离散化
F. 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 \quad l \quad r $ — Add all missing numbers from the interval $ [l, r] $
- $ 2 \quad l \quad r $ — Remove all present numbers from the interval $ [l, r] $
- $ 3 \quad l \quad 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 ≤ 10^5) $ .
Next $ n $ lines contain three integer numbers $ t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 10^18) $ — type of the query, left and right bounds.
Output
Print $ MEX $ of the set after each query.
Examples
input1
3
1 3 4
3 1 6
2 1 3
output1
1
3
1
input2
4
1 1 3
3 5 6
2 4 4
3 1 6
output2
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 $ 是把给定区间设为 $ 1 $ ,
操作 $ 2 $ 是把给定区间清零,
操作 $ 3 $ 是把给定区间反转。
每次操作后要输出最小位置的 $ 0 $ 。 -
数据范围:$ 1 \le n \le 10^5 $
思路
-
线段树+离散化
-
操作 $ 1 $ 和 $ 2 $ :区间赋值
-
操作 $ 3 $ :相当于区间每个数 $ xor \quad 1 $
-
可以维护线段树的区间长度,线段树上二分即可
-
注意:
- 求的是 $ mex $ ,可能不是 $ l_i,r_i $ 中的任何一个,对于 $ 1,l_{i+1},r_{i+1} $ 也要离散。
- 记录原来信息的数组必须得开 $ long \quad long $
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define N 400005
inline ll read() {
register char ch;
while(!isdigit(ch=getchar()));
register ll x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
int n,m,opt[N];
ll a[N<<2],ql[N],qr[N],sum[N<<2],lzy[N<<2],rev[N<<2];
inline void pushdown(int o,int l,int r){
int mid=l+r>>1;
if(lzy[o]){
lzy[o<<1]=lzy[o<<1|1]=lzy[o]--;
sum[o<<1]=(mid-l+1)*lzy[o];
sum[o<<1|1]=(r-mid)*lzy[o];
lzy[o]=rev[o<<1]=rev[o<<1|1]=0;
}
if(rev[o]){
sum[o<<1]=mid-l+1-sum[o<<1];
sum[o<<1|1]=r-mid-sum[o<<1|1];
rev[o<<1]^=1;
rev[o<<1|1]^=1;
rev[o]=0;
}
}
void updata(int o,int l,int r,int L,int R,int val){
if(L<=l&&r<=R){
lzy[o]=val--; rev[o]=0;
sum[o]=(val)*(r-l+1);
return;
}
pushdown(o,l,r);
int mid=l+r>>1;
if(L>mid) updata(o<<1|1,mid+1,r,L,R,val);
else if(R<=mid) updata(o<<1,l,mid,L,R,val);
else{
updata(o<<1,l,mid,L,R,val);
updata(o<<1|1,mid+1,r,L,R,val);
}
sum[o]=sum[o<<1]+sum[o<<1|1];
}
void modify(int o,int l,int r,int L,int R){
if(L<=l&&r<=R){
sum[o]=r-l+1-sum[o];
rev[o]^=1;
return;
}
pushdown(o,l,r);
int mid=l+r>>1;
if(L>mid) modify(o<<1|1,mid+1,r,L,R);
else if(R<=mid) modify(o<<1,l,mid,L,R);
else{
modify(o<<1,l,mid,L,R);
modify(o<<1|1,mid+1,r,L,R);
}
sum[o]=sum[o<<1]+sum[o<<1|1];
}
ll query(int o,int l,int r){
if(l==r) return a[l];
pushdown(o,l,r);
int mid=l+r>>1;
ll res;
if(sum[o<<1]!=mid-l+1) res=query(o<<1,l,mid);
else res=query(o<<1|1,mid+1,r);
sum[o]=sum[o<<1]+sum[o<<1|1];
return res;
}
signed main(){
n=read(); a[++m]=1;
for(int i=1;i<=n;++i){
opt[i]=read(); ql[i]=read(); qr[i]=read();
a[++m]=ql[i]; a[++m]=ql[i]+1;
a[++m]=qr[i]; a[++m]=qr[i]+1;
}
sort(a+1,a+1+m);
m=unique(a+1,a+1+m)-(a+1);
for(int i=1;i<=n;++i){
int L=lower_bound(a+1,a+1+m,ql[i])-a;
int R=lower_bound(a+1,a+1+m,qr[i])-a;
if(opt[i]==1||opt[i]==2) updata(1,1,m,L,R,opt[i]==1 ? 2 : 1);
else modify(1,1,m,L,R);
printf("%lld\n",query(1,1,m));
}
return 0;
}
/*
# 42702002
When 2018-09-09 14:03:14
Who PotremZ
Problem F - MEX Queries
Lang GNU C++11
Verdict Accepted
Time 264 ms
Memory 57900 KB
*/