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;
}

 

posted @ 2022-02-10 22:14  HYDcn666_JZOJ  阅读(62)  评论(0编辑  收藏  举报