题目描述
由于出题人懒所以没有背景。
一个无限长的$01$序列,初始全为$0$,每次选择一个区间$[l,r]$进行操作,有三种操作:
$\bullet 1\ l\ r$将$[l,r]$中所有元素变成$1$。
$\bullet 2\ l\ r$将$[l,r]$中所有元素变成$0$。
$\bullet 3\ l\ r$将$[l,r]$中所有元素异或上$1$。
每次操作后询问最左边的$0$在哪个位置。
输入格式
第一行一个数$m$,表示序列长度和操作数量。
接下来$m$行,每行三个数$ty\ l\ r$,描述一次操作。
输出格式
输出共$m$行,第$i$行输出一个数表示第$i$次操作后的答案。
样例
样例输入:
3
1 3 4
3 1 6
2 1 3
样例输出:
1
3
1
数据范围与提示
令$n$为$\max(r)$。
对于测试点$1\sim 4$:$n,m\leqslant 10^3$。
对于测试点$5\sim 6$:只有$1$操作。
对于测试点$7\sim 10$:只有$1,2$操作。
对于测试点$11\sim 15$:$n\leqslant 10^5$。
对于测试点$16\sim 20$:无特殊限制。
对于所有的数据,$n\leqslant 10^{18},m\leqslant 10^5$。
题解
看数据范围,肯定是要离散化的,但是离散化的时候需要注意还要将$l+1$和$r+1$离散。
对于只有操作$1,2$的情况,我们可以用线段树直接维护。
那么考虑情况$3$我们可以怎么处理。
如果一段区间都是一样的,我们可以直接将其翻转,然后$return$。
不过这样做可以被很轻松的卡掉,比方说序列是$0101010......$,每次都执行操作$3$,那么会被卡成$n^2$。
但是对于这到柯朵莉树都能$A$掉的题,这就无关紧要了。
时间复杂度:$\Theta(n)\sim \Theta(n^2)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> #define L(x) x<<1 #define R(x) x<<1|1 #define inf 0x3f3f3f3f using namespace std; map<long long,long long> mp; struct rec{int ty;long long l,r;}e[200001]; int m; int n; long long pre[5000000]; long long trsam[10000000],trans[10000000],lz[10000000]; void pushup(int x) { trans[x]=min(trans[L(x)],trans[R(x)]); trsam[x]=(trsam[L(x)]==trsam[R(x)])?trsam[L(x)]:-1; } void pushdown(int x,int l,int r) { if(lz[x]==-1)return; int mid=(l+r)>>1; lz[L(x)]=lz[R(x)]=trsam[L(x)]=trsam[R(x)]=lz[x]; if(!trsam[L(x)])trans[L(x)]=l; else trans[L(x)]=inf; if(!trsam[R(x)])trans[R(x)]=mid+1; else trans[R(x)]=inf; lz[x]=-1; } void build(int x,int l,int r) { trans[x]=inf; lz[x]=-1; if(l==r) { trans[x]=l; return; } int mid=(l+r)>>1; build(L(x),l,mid); build(R(x),mid+1,r); pushup(x); } void change(int x,int l,int r,int L,int R,int opt) { if(R<l||r<L)return; if(L<=l&&r<=R&&trsam[x]!=-1) { switch(opt) { case 1:trsam[x]=1;lz[x]=1;break; case 2:trsam[x]=0;lz[x]=0;break; case 3:trsam[x]^=1;lz[x]=trsam[x];break; } if(!trsam[x])trans[x]=l; else trans[x]=inf; return; } int mid=(l+r)>>1; pushdown(x,l,r); change(L(x),l,mid,L,R,opt); change(R(x),mid+1,r,L,R,opt); pushup(x); } int main() { scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d%lld%lld",&e[i].ty,&e[i].l,&e[i].r); for(int i=1;i<=m;++i) { pre[i*4-3]=e[i].l, pre[i*4-2]=e[i].r; pre[i*4-1]=e[i].l+1, pre[i*4]=e[i].r+1; } pre[m*4+1]=1; sort(pre+1,pre+m*4+2); n=unique(pre+1,pre+m*4+2)-pre-1; for(int i=1;i<=m;++i) { mp[lower_bound(pre+1,pre+n+1,e[i].r+1)-pre]=e[i].r+1; mp[lower_bound(pre+1,pre+n+1,e[i].l+1)-pre]=e[i].l+1; long long now=e[i].l; e[i].l=lower_bound(pre+1,pre+n+1,e[i].l)-pre; mp[e[i].l]=now; now=e[i].r; e[i].r=lower_bound(pre+1,pre+n+1,e[i].r)-pre; mp[e[i].r]=now; } mp[1]=1; build(1,1,n); for(int i=1;i<=m;++i) { change(1,1,n,e[i].l,e[i].r,e[i].ty); printf("%lld\n",mp[trans[1]]); } return 0; }
rp++
原文地址:https://www.cnblogs.com/wzc521/p/11615873.html