洛谷 U140359 批量处理
洛谷 U140359 批量处理
题目背景
不知为何,人们常常把“程序员”一词和繁重而单调的工作、秃顶、快速变老和家庭破败等负面词汇联系在一起。SeawaySeawa**y一直对这种看法持以怀疑。直到他找到了一份工作,他发现这份工作恰恰像上面描述的那样,这份工作叫“批处理工程师”......
题目描述
顾名思义,批处理工程师的任务就是对一堆数据进行批量处理。这种对数据的批量处理包括但不限于做表格、写文案、做PPT、文档编辑等。现在,SeawaySeawa**y的上家交给他一个这样的任务:维护集合。
具体地,这个任务被这样描述:
最初始的集合是空集。这个任务有一个维护值域DD。一共有3种操作可以对当前集合进行维护。分别是:
1号操作:把[l,r][l,r]中在集合中没有出现过的数添加到集合中。
2号操作:把[l,r][l,r]中在集合中出现过的数从集合中删除。
3号操作:对[l,r][l,r]中同时执行1号、2号操作。这里的同时执行是指:把[l,r][l,r]中在集合中没有出现过的数添加到集合中,同时,把[l,r][l,r]中在集合中出现过的数从集合中删除。
并且,为了检查SeawaySeawa**y的任务完成情况,他的上家在每次操作之后都会检查他操作的正确性。具体地,一个检查被这样描述:
每次操作后,输出整个集合的mexmex值。
注:mexmex值的定义是:在集合中没有出现过的最小的数。
输入格式
从文件operate.inoperate.i**n中读入数据。
第一行一个整数nn,表示操作数量。
接下来的nn行,每行三个整数opt,l,ropt,l,r,其中optopt表示操作种类,l,rl,r表示操作区间。
输出格式
输出到文件operate.outoperate.out中。
共nn行,每行一个整数ans_ians**i,表示第ii次操作后的整个集合的mexmex值。
题解:
一看就是数据结构题。没啥说的了。
但是作为数据结构题,细节越多评分越高。对于这种还掺杂着其他知识点,并且细节巨多的线段树,它的评分就直接飙到紫了。
我觉得有点不太配这个难度,评蓝还是比较中肯的,但是大家都说是紫,那就紫吧,反正确实也不简单。
怕写挂的就去写暴力分,应该给了30分?
也给了60分的不需要离散化的线段树。所以差不多给了60的分,很良心了吧。
正解是线段树+离散化。
首先要离散化,这里就有难点,离散的时候不能只离散左右端点,还要把1和右端点+1也离散进去,为什么呢?因为r+1有可能被算成答案,所以不能一股脑的离散掉。
然后就是线段树了,维护三种操作:区间置零,区间置1,区间反转。这个地方的实现重点是lazy标记的下传先后顺序。查询的时候先查左子树即可。
代码:
#include<cstdio>
#include<algorithm>
#define int long long
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=1e5+5;
int n;
int opt[maxn],l[maxn],r[maxn];
int a[maxn<<2],cnt;
int sum[maxn<<4],lazy[maxn<<4],rev[maxn<<4];
//sum求和,lazy赋值,rev反转
void pushup(int pos)
{
sum[pos]=sum[lson]+sum[rson];
}
void build(int pos,int l,int r)
{
int mid=(l+r)>>1;
lazy[pos]=-1;
if(l==r)
return;
build(lson,l,mid);
build(rson,mid+1,r);
}
void mark(int pos,int l,int r,int k)
{
if(k==1)
{
sum[pos]=(r-l+1);
lazy[pos]=1;
rev[pos]=0;
}
else if(k==2)
{
lazy[pos]=0;
sum[pos]=0;
rev[pos]=0;
}
else
{
if(lazy[pos]!=-1)
lazy[pos]^=1;
else
rev[pos]^=1;
sum[pos]=(r-l+1)-sum[pos];
}
}
void pushdown(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(lazy[pos]==1)
{
mark(lson,l,mid,1);
mark(rson,mid+1,r,1);
lazy[pos]=-1;
}
else if(lazy[pos]==0)
{
mark(lson,l,mid,2);
mark(rson,mid+1,r,2);
lazy[pos]=-1;
}
if(rev[pos])
{
mark(lson,l,mid,3);
mark(rson,mid+1,r,3);
rev[pos]=0;
}
}
void update(int pos,int l,int r,int x,int y,int k)
{
int mid=(l+r)>>1;
if(l==r)
{
if(k==1)
sum[pos]=1;
else if(k==2)
sum[pos]=0;
else
sum[pos]^=1;
return;
}
if(x<=l && r<=y)
{
mark(pos,l,r,k);
return;
}
pushdown(pos,l,r);
if(x<=mid)
update(lson,l,mid,x,y,k);
if(y>mid)
update(rson,mid+1,r,x,y,k);
pushup(pos);
}
int query(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
return l;
pushdown(pos,l,r);
if(sum[lson]<(mid-l+1))
return query(lson,l,mid);
else
return query(rson,mid+1,r);
}
signed main()
{
scanf("%lld",&n);
a[++cnt]=1;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&opt[i],&l[i],&r[i]);
a[++cnt]=l[i];a[++cnt]=r[i];a[++cnt]=r[i]+1;
}
sort(a+1,a+cnt+1);
cnt=unique(a+1,a+cnt+1)-(a+1);
build(1,1,cnt);
for(int i=1;i<=n;i++)
{
l[i]=lower_bound(a+1,a+cnt+1,l[i])-a;
r[i]=lower_bound(a+1,a+cnt+1,r[i])-a;
update(1,1,cnt,l[i],r[i],opt[i]);
printf("%lld\n",a[query(1,1,cnt)]);
}
return 0;
}