CF817F MEX Queries
https://www.luogu.com.cn/problem/CF817F
线段树
数据范围极大,需要离散化
可以转换一下操作:
\(1.\)将\([l,r]\)区间赋值为\(1\)
\(2.\)将\([l,r]\)区间赋值为\(0\)
\(3.\)将\([l,r]\)区间\(0\)变成\(1\),\(1\)变成\(0\)
用\(lazy\)记录当前位置的状态
\(0:\)该区间没有操作
\(1:\)该区间被全部覆盖
\(2:\)该区间被全部删除
\(3:\)该区间被全部反转
注意,\(lazy_1,lazy_2\)可以直接覆盖以前的\(lazy\),但操作\(lazy_3\)需要判断一下
\(lazy_0+lazy_3=lazy_3\)
\(lazy_1+lazy_3=lazy_2\)
\(lazy_2+lazy_3=lazy_1\)
\(lazy_3+lazy_3=lazy_0\)
\(OK!\)
\(C++ Code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 200005
using namespace std;
int n,m,cnt,cc;
struct Ques
{
int opt;
ll l,r;
}q[N];
ll g[N*3];
struct node
{
int s,lazy;
}t[N << 5];
void down_tag(int p,int l,int r,int z)
{
switch (z)
{
case 1:
t[p].s=r-l+1;
t[p].lazy=1;
break;
case 2:
t[p].s=0;
t[p].lazy=2;
break;
case 3:
t[p].s=r-l+1-t[p].s;
switch (t[p].lazy)//lazy3的特判
{
case 0:
t[p].lazy=3;
break;
case 1:
t[p].lazy=2;
break;
case 2:
t[p].lazy=1;
break;
case 3:
t[p].lazy=0;
break;
}
break;
}
}
void down(int p,int l,int r)
{
if (!t[p].lazy)
return;
int mid=(l+r) >> 1;
down_tag(p+p,l,mid,t[p].lazy);
down_tag(p+p+1,mid+1,r,t[p].lazy);
t[p].lazy=0;
}
void change(int p,int l,int r,int x,int y,int z)
{
if (l>y||r<x)
return;
if (x<=l&&r<=y)
{
down_tag(p,l,r,z);
return;
}
down(p,l,r);
int mid=(l+r) >> 1;
change(p+p,l,mid,x,y,z);
change(p+p+1,mid+1,r,x,y,z);
t[p].s=t[p+p].s+t[p+p+1].s;
}
#define dis(x,y) (y-x+1)
int query(int p,int l,int r)
{
if (l==r)
return l;
down(p,l,r);
int mid=(l+r) >> 1;
if (t[p+p].s<dis(l,mid))
return query(p+p,l,mid); else
return query(p+p+1,mid+1,r);
}
int main()
{
scanf("%d",&m);
g[++cnt]=1;
for (int i=1;i<=m;i++)
{
scanf("%d%lld%lld",&q[i].opt,&q[i].l,&q[i].r);
g[++cnt]=q[i].l;
g[++cnt]=q[i].r;
g[++cnt]=q[i].r+1;
}
sort(g+1,g+cnt+1);//离散化
cc=unique(g+1,g+cnt+1)-g-1;
for (int i=1;i<=m;i++)
{
q[i].l=lower_bound(g+1,g+cc+1,q[i].l)-g;
q[i].r=lower_bound(g+1,g+cc+1,q[i].r)-g;
change(1,1,cc,q[i].l,q[i].r,q[i].opt);
printf("%lld\n",g[query(1,1,cc)]);
}
return 0;
}