Codeforces - 817F. MEX Queries
Posted linzhuohang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces - 817F. MEX Queries相关的知识,希望对你有一定的参考价值。
题目
给你一个无限长的数组,初始的时候都为0,有3种操作:
操作1是把给定区间[l,r][l,r] 设为1,
操作2是把给定区间[l,r][l,r] 设为0,
操作3把给定区间[l,r][l,r] 0,1反转。
l,r<=1018
一共n(n<=105)个操作,每次操作后要输出最小位置的0。
解法
看到维护区间,想到线段树。
看到数据范围,想到把操作离线然后离散化。
然后再yy一下合并状态:
每个节点维护两个信息:
min0表示该区间最小位置的0,初始值为l (当时错在了这里)。
min1表示该区间最小位置的1,初始值为inf。
合并时左右取最小即可
操作
- min0=inf,min1=l
- min0=l,min1=inf
- 交换min0,min1
通过懒标记维护。
一些细节问题
- 离散化时要把r+1也一同离散化,否则 (r0,l1)这段区间会遗失。(当时错在了这里*2)
- pushdown的时候可能同时会有反转和修改操作,为了防止顺序出错,要做点处理(当时错在了这里*3)
- 反转标记在前,修改操作在后:可以直接无视掉反转标记。所以要在打标记前清除反转标记。
- 反转标记在后,修改操作在前:必须先处理修改操作。所以pushdown函数里修改要写在反转的前面
- 数组要开n*3*4(每个操作最多有三个数,线段树空间要*4)(当时错在了这里*4)
代码
#include<algorithm> #include<iostream> #include<cstdio> #include<map> using namespace std; #define N 5000000 #define int long long #define root 1,1,maxn #define mid (l+r)/2 #define ls id*2 #define rs id*2+1 #define lc ls,l,mid,tl,tr #define rc rs,mid+1,r,tl,tr #define inf 4611686018427387904 int min0[N],min1[N],dic[N],tag[N],maxn,neg[N]; struct opt int type,l,r; opts[N]; map<int,int> m; void pushdown(int id,int l,int r) if(tag[id]) tag[ls]=tag[rs]=tag[id]; neg[ls]=neg[rs]=0; if(tag[id]-1>0) min0[ls]=min0[rs]=inf,min1[ls]=l,min1[rs]=mid+1; else min0[ls]=l,min0[rs]=mid+1,min1[ls]=min1[rs]=inf; if(neg[id]) //if(tag[ls]||tag[rs]) throw ‘a‘; neg[ls]=!neg[ls],neg[rs]=!neg[rs]; swap(min0[ls],min1[ls]); swap(min0[rs],min1[rs]); neg[id]=tag[id]=0; void update(int id) min0[id]=min(min0[ls],min0[rs]); min1[id]=min(min1[ls],min1[rs]); void set(int id,int l,int r,int tl,int tr,int v) if(l>=tl&&r<=tr) if(v) min0[id]=inf,min1[id]=l; else min0[id]=l,min1[id]=inf; tag[id]=v+1; neg[id]=0; return; pushdown(id,l,r); if(tl<=mid) set(lc,v); if(tr>mid) set(rc,v); update(id); void set2(int id,int l,int r,int tl,int tr) if(l>=tl&&r<=tr) swap(min0[id],min1[id]); neg[id]=!neg[id]; return; pushdown(id,l,r); if(tl<=mid) set2(lc); if(tr>mid) set2(rc); update(id); void build(int id,int l,int r) min0[id]=l; min1[id]=inf; if(l==r) return; build(ls,l,mid); build(rs,mid+1,r); signed main() int n,cnt=0; //freopen("data.in","r",stdin); //freopen("my.out","w",stdout); cin>>n; for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&opts[i].type,&opts[i].l,&opts[i].r); if(!opts[i].l||!opts[i].r) throw "a"; m[opts[i].l]=1; m[opts[i].r]=1; m[opts[i].r+1]=1; m[1]=1; for(map<int,int>::iterator it=m.begin();it!=m.end();it++)//通过map离散化 dic[++cnt]=(*it).first; (*it).second=cnt; maxn=m.size(); build(root); for(int i=1;i<=n;i++) if(opts[i].type<=2) set(root,m[opts[i].l],m[opts[i].r],opts[i].type==1); else set2(root,m[opts[i].l],m[opts[i].r]); printf("%lld\n",dic[min0[1]]);
以上是关于Codeforces - 817F. MEX Queries的主要内容,如果未能解决你的问题,请参考以下文章