题目
思路
很裸的线段树。对于每次修改,将 \(l,r,r+1\) 插入数组中,然后将数组中的数字离散化。
每次修改注意标记的下传。询问直接类似权值线段树即可。
时间复杂度 \(O(n\log n)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000010;
int Q,tot;
ll b[N];
struct Query
{
ll l,r,opt;
}ask[N];
struct SegTree
{
int l[N*4],r[N*4],sum[N*4],len[N*4],lazy[N*4];
void build(int x,int ql,int qr)
{
l[x]=ql; r[x]=qr; len[x]=qr-ql+1;
if (ql==qr) return;
int mid=(ql+qr)>>1;
build(x*2,ql,mid); build(x*2+1,mid+1,qr);
}
void pushdown(int x)
{
if (lazy[x])
{
if (lazy[x]==1) sum[x*2]=len[x*2],sum[x*2+1]=len[x*2+1];
if (lazy[x]==2) sum[x*2]=sum[x*2+1]=0;
if (lazy[x]==3) sum[x*2]=len[x*2]-sum[x*2],sum[x*2+1]=len[x*2+1]-sum[x*2+1];
if (lazy[x]==3)
lazy[x*2]=3-lazy[x*2],lazy[x*2+1]=3-lazy[x*2+1];
else
lazy[x*2]=lazy[x*2+1]=lazy[x];
lazy[x]=0;
}
}
void pushup(int x)
{
sum[x]=sum[x*2]+sum[x*2+1];
}
void update(int x,int ql,int qr,int opt)
{
pushdown(x);
if (l[x]==ql && r[x]==qr)
{
if (opt==1) sum[x]=len[x];
if (opt==2) sum[x]=0;
if (opt==3) sum[x]=len[x]-sum[x];
lazy[x]=opt;
return;
}
pushdown(x);
int mid=(l[x]+r[x])>>1;
if (qr<=mid) update(x*2,ql,qr,opt);
else if (ql>mid) update(x*2+1,ql,qr,opt);
else update(x*2,ql,mid,opt),update(x*2+1,mid+1,qr,opt);
pushup(x);
}
void query(int x)
{
pushdown(x);
if (l[x]==r[x])
{
printf("%lld\n",b[l[x]]);
return;
}
pushdown(x);
if (sum[x*2]<len[x*2]) query(x*2);
else query(x*2+1);
}
}seg;
int main()
{
scanf("%d",&Q);
b[++tot]=1LL;
for (int i=1;i<=Q;i++)
{
scanf("%lld%lld%lld",&ask[i].opt,&ask[i].l,&ask[i].r);
b[++tot]=ask[i].l; b[++tot]=ask[i].r;
b[++tot]=ask[i].l+1; b[++tot]=ask[i].r+1;
}
sort(b+1,b+1+tot);
tot=unique(b+1,b+1+tot)-b-1;
for (int i=1;i<=Q;i++)
{
ask[i].l=lower_bound(b+1,b+1+tot,ask[i].l)-b;
ask[i].r=lower_bound(b+1,b+1+tot,ask[i].r)-b;
}
seg.build(1,1,tot);
for (int i=1;i<=Q;i++)
{
int opt=ask[i].opt,l=ask[i].l,r=ask[i].r;
seg.update(1,l,r,opt);
seg.query(1);
}
return 0;
}