正题
题目大意
无限长的010101序列,每次进行一个操作
- 区间内赋值为000
- 区间内赋值为111
- 区间取反
求第一个000的位置
解题思路
离散化(储存每个区间的左右端点和他们加一之后的值)后可以用线段树储存第一个000和第一个111的位置。然后区间取反时就交换两个值并且让lazylazylazy标记同样取反即可
时间复杂度O(nlogn)O(n\log n)O(nlogn)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e5+10;
ll n,m,l[N],r[N],op[N],a[N];
ll minw[N*4],minb[N*4],lazy[N*4];
void Downdata(ll x,ll l,ll r,ll op){if(op==3&&lazy[x]){if(lazy[x]==1)lazy[x]=2;else if(lazy[x]==2)lazy[x]=1;else if(lazy[x]==3)lazy[x]=0;}else lazy[x]=op;if(op==1)minw[x]=l,minb[x]=n+1;else if(op==2)minw[x]=n+1,minb[x]=l;else swap(minw[x],minb[x]);return;
}
void Change(ll x,ll L,ll R,ll l,ll r,ll op){if(L==l&&R==r){Downdata(x,l,r,op);return;}ll mid=(L+R)>>1;if(lazy[x]){Downdata(x*2,L,mid,lazy[x]);Downdata(x*2+1,mid+1,R,lazy[x]);lazy[x]=0;}if(r<=mid)Change(x*2,L,mid,l,r,op);else if(l>mid)Change(x*2+1,mid+1,R,l,r,op);else Change(x*2,L,mid,l,mid,op),Change(x*2+1,mid+1,R,mid+1,r,op);minw[x]=min(minw[x*2],minw[x*2+1]);minb[x]=min(minb[x*2],minb[x*2+1]);return;
}
int main()
{scanf("%lld",&m);for(ll i=1;i<=m;i++){scanf("%lld%lld%lld",&op[i],&l[i],&r[i]);a[++n]=l[i];a[++n]=r[i];a[++n]=l[i]+1;a[++n]=r[i]+1;}a[++n]=1;sort(a+1,a+1+n);n=unique(a+1,a+1+n)-a-1;a[n+1]=a[n]+1;for(ll i=1;i<N*4;i++)minb[i]=minw[i]=n+1;Change(1,1,n,1,n,2);for(ll i=1;i<=m;i++){l[i]=lower_bound(a+1,a+1+n,l[i])-a;r[i]=lower_bound(a+1,a+1+n,r[i])-a;Change(1,1,n,l[i],r[i],op[i]);printf("%lld\n",a[minb[1]]);}
}