卧薪尝胆,厚积薄发。
MEX Queries
Date: Thu Jul 12 00:14:31 CST 2018 In Category: NoCategory

Description:

给你一个无限长的数组,初始的时候都为 $0$ ,操作 $1$ 是把给定区间清零,操作 $2$ 是把给定区间设为 $1$ ,操作 $3$ 把给定区间反转。每次操作后要输出最小位置的 $0$ 。
$1\le N \le 10^5$ $1\le l,r \le 10^{18}$

Solution:

先将范围离散化,将每个出现的数据保留下来,连续的缩成一个块,因为最小值可能在那里出现,区间置一置零打标记即可,但区间反转标记不能随便下放,因为子节点可能已经打了其他的标记,直接给子节点打反转标记会有标记丢失,于是在下放时子节点标记为 $2-$ 标记,这样原来置一的置零,原来置零的置一,原来反转的不再反转,就可以下放了。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
using namespace std;
#define MAXN 600010
int n;
typedef long long ll;
struct change
{
ll l,r;
int type;
}c[MAXN];
ll s[MAXN];
int tot = 0;
map<ll,int> to;
ll fr[MAXN];
struct node
{
int lc,rc,sum;
int tag;
node(){tag = -1;}
}t[MAXN << 1];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
rt = newnode();
if(l == r)return;
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
return;
}
void pushdown(int rt,int l,int r)
{
if(t[rt].tag == -1)return;
if(t[rt].tag == 0)
{
t[t[rt].lc].tag = t[t[rt].rc].tag = 0;
t[t[rt].lc].sum = t[t[rt].rc].sum = 0;
}
if(t[rt].tag == 1)
{
t[t[rt].lc].tag = t[t[rt].rc].tag = 1;
t[t[rt].lc].sum = (mid - l + 1);t[t[rt].rc].sum = (r - mid);
}
if(t[rt].tag == 2)
{
t[t[rt].lc].tag = 1 - t[t[rt].lc].tag;
t[t[rt].rc].tag = 1 - t[t[rt].rc].tag;
t[t[rt].lc].sum = (mid - l + 1) - t[t[rt].lc].sum;
t[t[rt].rc].sum = (r - mid) - t[t[rt].rc].sum;
}
t[rt].tag = -1;
return;
}
void add(int rt,int L,int R,int l,int r)
{
pushdown(rt,l,r);
if(L <= l && r <= R)
{
t[rt].sum = (r - l + 1);
t[rt].tag = 1;
return;
}
if(L <= mid)add(t[rt].lc,L,R,l,mid);
if(R > mid)add(t[rt].rc,L,R,mid + 1,r);
t[rt].sum = t[t[rt].lc].sum + t[t[rt].rc].sum;
return;
}
void del(int rt,int L,int R,int l,int r)
{
pushdown(rt,l,r);
if(L <= l && r <= R)
{
t[rt].sum = 0;
t[rt].tag = 0;
return;
}
if(L <= mid)del(t[rt].lc,L,R,l,mid);
if(R > mid)del(t[rt].rc,L,R,mid + 1,r);
t[rt].sum = t[t[rt].lc].sum + t[t[rt].rc].sum;
return;
}
void rev(int rt,int L,int R,int l,int r)
{
pushdown(rt,l,r);
if(L <= l && r <= R)
{
t[rt].tag = 2;
t[rt].sum = (r - l + 1) - t[rt].sum;
return;
}
if(L <= mid)rev(t[rt].lc,L,R,l,mid);
if(R > mid)rev(t[rt].rc,L,R,mid + 1,r);
t[rt].sum = t[t[rt].lc].sum + t[t[rt].rc].sum;
return;
}
ll query(int rt,int l,int r)
{
if(l == r)return fr[l];
pushdown(rt,l,r);
if(t[t[rt].lc].sum == (mid - l + 1))return query(t[rt].rc,mid + 1,r);
else return query(t[rt].lc,l,mid);
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)
{
scanf("%d%I64d%I64d",&c[i].type,&c[i].l,&c[i].r);
s[++tot] = c[i].l;s[++tot] = c[i].r;
}
sort(s + 1,s + 1 + tot);
tot = 0;
ll cur = 0;
for(int i = 1;i <= 2 * n;++i)
{
if(s[i] == s[i - 1])continue;
if(s[i] != cur + 1){++tot;fr[tot] = cur + 1;}
to[s[i]] = ++tot;cur = s[i];fr[tot] = s[i];
}
++tot;fr[tot] = cur + 1;
build(root,1,tot);
for(int i = 1;i <= n;++i)
{
if(c[i].type == 1)
{
add(root,to[c[i].l],to[c[i].r],1,tot);
}
if(c[i].type == 2)
{
del(root,to[c[i].l],to[c[i].r],1,tot);
}
if(c[i].type == 3)
{
rev(root,to[c[i].l],to[c[i].r],1,tot);
}//pt(root,1,tot);puts("");
printf("%I64d\n",query(root,1,tot));
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡