AtCoder Beginner Contest 237 G - Range Sort Query
题目大意
一个1~n的排列,进行m次区间升/降序排序操作,问x最终所在的位置。
思路
这道题不复杂,但不好想,还容易想到一些没用的方法(如平衡树)。
我们尝试换个思路,我们要找的这个位置的值满足>=x且不满足>=x+1。
这看起来是废话(与=x完全等价),但是可以拆分上面两个限制条件,将排列变为两个只含0/1的序列,最终满足一个为0一个为1的位置就是答案。
这样,区间排序就很容易了,我们只在乎0/1,不在乎取值,0和1各自放一起,直接用线段树维护就好。
具体来说,查找区间内0/1个数,前面放0/1,后面放1/0,即为排序。
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define inf 1000000007
using namespace std;
int n,m,T,pos;
struct node
{
int t[1000005][2],tag[1000005];
void build(int l,int r,int k)
{
t[k][0]=r-l+1;
if(l==r)return;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
}
void pushdown(int l,int r,int k)
{
int v=tag[k];
if(!v)return;
tag[k*2]=tag[k*2+1]=v;
v--;
t[k*2][v]=mid-l+1,t[k*2][v^1]=0;
t[k*2+1][v]=r-mid,t[k*2+1][v^1]=0;
tag[k]=0;
}
void fix(int l,int r,int k,int x,int y,int v)
{
if(x>y)return;
if(l<r)pushdown(l,r,k);
if(l==x&&r==y)
{
t[k][v]=r-l+1,t[k][v^1]=0;
if(l<r)tag[k]=v+1;
return;
}
if(y<=mid)fix(l,mid,k*2,x,y,v);
else if(x>mid)fix(mid+1,r,k*2+1,x,y,v);
else fix(l,mid,k*2,x,mid,v),fix(mid+1,r,k*2+1,mid+1,y,v);
t[k][0]=t[k*2][0]+t[k*2+1][0];
t[k][1]=t[k*2][1]+t[k*2+1][1];
}
int find(int l,int r,int k,int x,int y,int v)
{
if(l<r)pushdown(l,r,k);
if(l==x&&r==y)
{
return t[k][v];
}
if(y<=mid)return find(l,mid,k*2,x,y,v);
else if(x>mid)return find(mid+1,r,k*2+1,x,y,v);
else return find(l,mid,k*2,x,mid,v)+find(mid+1,r,k*2+1,mid+1,y,v);
t[k][0]=t[k*2][0]+t[k*2+1][0];
t[k][1]=t[k*2][1]+t[k*2+1][1];
}
void rev(int l,int r,int k)
{
int mad=find(1,n,1,l,r,k);
fix(1,n,1,l,l+mad-1,k);
fix(1,n,1,l+mad,r,k^1);
}
}ta,tb;
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*f;
}
void calc(int l,int r,int k)
{
if(l==r)
{
if(ta.t[k][0]^tb.t[k][0])
{
pos=l;
}
return;
}
ta.pushdown(l,r,k);
tb.pushdown(l,r,k);
calc(l,mid,k*2);
calc(mid+1,r,k*2+1);
}
int main()
{
n=read(),m=read(),T=read();
ta.build(1,n,1);
tb.build(1,n,1);
for(int i=1,x;i<=n;i++)
{
x=read();
if(x>=T)
{
ta.fix(1,n,1,i,i,1);
}
if(x>=T+1)
{
tb.fix(1,n,1,i,i,1);
}
}
for(int i=1,opt,l,r;i<=m;i++)
{
opt=read(),l=read(),r=read();
ta.rev(l,r,opt-1);
tb.rev(l,r,opt-1);
}
calc(1,n,1);
printf("%d\n",pos);
return 0;
}