题目链接:点击查看
题目大意:初始时有一个空的集合,需要执行 n 次操作:
- 1 l r:将区间 [ l , r ] 内未出现的数加入到集合中
- 2 l r:将区间 [ l , r ] 内出现的数字全部删除
- 3 l r:将区间 [ l , r ] 内未出现的数加入到集合中,同时将区间 [ l , r ] 内出现过的数字全部删除
每次操作后取集合的 MEX
题目分析:HDU - 3397 的弱化版
简化版题意就是,初始时有一个全 0 的序列,操作 1 是将区间内的数全部修改为 1,操作 2 是将区间内的数全部修改为 0,操作 3 是将区间内的数全部置反,即 0 变为 1,1 变为 0,每次询问需要回答从左侧开始首次出现的 0 的位置,三个操作其实就是一个比较基础的 lazy 序的实现,一个控制区间覆盖,一个控制区间翻转,而对于每次询问只需要在线段树上行整体二分就可以轻松得到答案了
需要注意的是因为区间范围非常的大,所以需要离线去做,先将区间离散化一下,因为对于某段操作 [ l , r ] 来说,只会影响到 l - 1 和 r + 1 ,所以离散化的时候多离散化几个点就好了
代码:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e6+100;
vector<LL>node;
int n;
struct qu
{
int op;
LL l,r;
void input()
{
scanf("%d%lld%lld",&op,&l,&r);
node.push_back(l);
node.push_back(r);
node.push_back(max(1LL,l-1));
node.push_back(max(1LL,r-1));
node.push_back(l+1);
node.push_back(r+1);
}
}q[N];
void discreate()
{
node.push_back(1);
sort(node.begin(),node.end());
node.erase(unique(node.begin(),node.end()),node.end());
for(int i=1;i<=n;i++)
{
q[i].l=lower_bound(node.begin(),node.end(),q[i].l)-node.begin();
q[i].r=lower_bound(node.begin(),node.end(),q[i].r)-node.begin();
}
}
struct Node
{
int l,r,len,sum,lazy1,lazy2;
}tree[N<<2];
void pushup(int k)
{
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
void pushdown(int k)
{
if(tree[k].lazy1!=-1)
{
tree[k<<1].lazy2=tree[k<<1|1].lazy2=0;
int lz=tree[k].lazy1;
tree[k].lazy1=-1;
tree[k<<1].lazy1=tree[k<<1|1].lazy1=lz;
tree[k<<1].sum=tree[k<<1].len*lz;
tree[k<<1|1].sum=tree[k<<1|1].len*lz;
}
if(tree[k].lazy2)
{
int lz=tree[k].lazy2;
tree[k].lazy2=0;
tree[k<<1].lazy2^=1;
tree[k<<1|1].lazy2^=1;
tree[k<<1].sum=tree[k<<1].len-tree[k<<1].sum;
tree[k<<1|1].sum=tree[k<<1|1].len-tree[k<<1|1].sum;
}
}
void build(int k,int l,int r)
{
tree[k].l=l;
tree[k].r=r;
tree[k].len=r-l+1;
tree[k].lazy1=-1;
tree[k].lazy2=0;
tree[k].sum=0;
if(l==r)
return;
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void update(int k,int l,int r,int op)//op=1,2,3
{
if(tree[k].l>r||tree[k].r<l)
return;
if(tree[k].l>=l&&tree[k].r<=r)
{
if(op==1)
{
tree[k].sum=tree[k].len;
tree[k].lazy1=1;
tree[k].lazy2=0;
}
else if(op==2)
{
tree[k].sum=0;
tree[k].lazy1=0;
tree[k].lazy2=0;
}
else if(op==3)
{
tree[k].sum=tree[k].len-tree[k].sum;
tree[k].lazy2^=1;
}
return;
}
pushdown(k);
update(k<<1,l,r,op);
update(k<<1|1,l,r,op);
pushup(k);
}
int query(int k)
{
if(tree[k].l==tree[k].r)
return tree[k].l;
pushdown(k);
if(tree[k<<1].sum!=tree[k<<1].len)
return query(k<<1);
else
return query(k<<1|1);
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
scanf("%d",&n);
for(int i=1;i<=n;i++)
q[i].input();
discreate();
build(1,0,node.size()-1);
for(int i=1;i<=n;i++)
{
update(1,q[i].l,q[i].r,q[i].op);
printf("%lld\n",node[query(1)]);
}
return 0;
}