【CodeForces817F】MEX Queries
阿新 • • 發佈:2020-08-11
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 \ge 1\)) integer number which is not presented in the set.
輸入格式
The first line contains one integer number \(n\)
Next \(n\) lines contain three integer numbers \(t, l, r\) (\(1 \le t \le 3, 1 \le l \le r \le 10^{18}\)) — type of the query, left and right bounds.
輸出格式
Print \(MEX\) of the set after each query.
樣例輸入1
3 1 3 4 3 1 6 2 1 3
樣例輸出1
1 3 1
樣例輸入2
4 1 1 3 3 5 6 2 4 4 3 1 6
樣例輸出2
4 4 4 1
題解
題意:維護一個集合,有三種操作,第一種操作將區間\([l,r]\)內所有元素加入集合中;第二種操作將區間\([l,r]\)內所有在集合內的元素從集合中刪除;第三種操作將區間\([l,r]\)中所有在集合內的元素刪除,不在集合內的元素加入集合。
要求每次操作後輸出最小的沒有在集合內的元素。
很明顯是一道線段樹水題,每次區間修改加上懶標記就好了。
但是我們發現這裡區間的範圍在\(1e18\)內,所幸修改運算元在\(1e5\)內,所以我們可以離散化一下。
因為如果直接離散化\(l,r\)的話邊界情況會比較難處理,每次操作要離散3個點,所以我這裡是離散化\(l,r+1\),把區間離散化而不是把點離散化。
上程式碼:
#include<bits/stdc++.h>
using namespace std;
int n;
struct aa{
int t;
long long l,r;
}a[500009];
int lt=1;
struct cc{
long long s;
int from;
bool k;
}to[500009];
struct bb{
int x;
int ld;
}p[4000009];
bool cmp(cc x,cc y){return x.s<y.s;}
void dn(int u,int l,int r){
if(p[u].ld&(1<<2)){
p[u*2].ld=p[u*2+1].ld=(1<<2);
p[u].x=r-l;
}
if(p[u].ld&(1<<1)){
p[u*2].ld=p[u*2+1].ld=(1<<1);
p[u].x=0;
}
if(p[u].ld&1){
p[u].x=r-l-p[u].x;
if(p[u*2].ld&(1<<2)) p[u*2].ld=(1<<1);
else if(p[u*2].ld&(1<<1)) p[u*2].ld=(1<<2);
else p[u*2].ld^=1;
if(p[u*2+1].ld&(1<<2)) p[u*2+1].ld=(1<<1);
else if(p[u*2+1].ld&(1<<1)) p[u*2+1].ld=(1<<2);
else p[u*2+1].ld^=1;
}
p[u].ld=0;
}
void dfs(int u,int l,int r,int x){
dn(u,l,r);
if(r<=a[x].l || l>=a[x].r) return;
if(l>=a[x].l && r<=a[x].r){
p[u].ld=(1<<(3-a[x].t));
dn(u,l,r);
if(r==l+1) return;
dn(u*2,l,(l+r)/2);
dn(u*2+1,(l+r)/2,r);
p[u].x=p[u*2].x+p[u*2+1].x;
return;
}
if(r==l+1) return;
dfs(u*2,l,(l+r)/2,x);
dfs(u*2+1,(l+r)/2,r,x);
p[u].x=p[u*2].x+p[u*2+1].x;
}
void fd(int u,int l,int r){
dn(u,l,r);
if(p[u].x==0){
printf("%lld\n",to[l].s);
return;
}
else if(p[u].x==r-l){
printf("%lld\n",to[r].s);
return;
}else{
dn(u*2,l,(l+r)/2);
if(p[u*2].x==(l+r)/2-l) fd(u*2+1,(l+r)/2,r);
else fd(u*2,l,(l+r)/2);
}
}
int main(){
scanf("%d",&n);
for(int j=1;j<=n;j++){
scanf("%d%lld%lld",&a[j].t,&a[j].l,&a[j].r);
a[j].r++;
to[j*2-1].s=a[j].l;
to[j*2-1].from=j;
to[j*2].s=a[j].r;
to[j*2].from=j;
to[j*2].k=1;
}
to[n*2+1].s=1;
sort(to+1,to+n*2+2,cmp);
if(to[1].k) a[to[1].from].r=1;
else a[to[1].from].l=1;
for(int j=2;j<=n*2+1;j++){
if(to[j].s!=to[lt].s) to[++lt]=to[j];
if(to[j].k) a[to[j].from].r=lt;
else a[to[j].from].l=lt;
}
for(int j=1;j<=n;j++){
dfs(1,1,lt,j);
fd(1,1,lt);
}
return 0;
}