DZY Loves Sorting HDU - 5649 & P2824排序

written on 2022-05-02

here

这类题最显著的特征是询问只有一个点,并且与相对大小有关。这种时候就可以采用这样的做法:

  1. 将普通序列问题转化为01问题,以此在一般的线段树(以序列下标为下标)上维护信息获得高效解答。

  2. 转为01问题,意思就是大于等于某数的写为1,小于的写为0.

  3. 二分答案,这时的答案显然具有单调性(想想左右两端点1,n)

于是该问题获解

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m,k,a[N];
struct Seg
{
	int val[N<<2],add[N<<2];
	void build(int p,int l,int r,int k)
	{
		val[p]=0,add[p]=-1;
		if(l==r)
		{
			if(a[l]<k) val[p]=0;
			else val[p]=1;
			return ;
		}
		int mid=l+r>>1;
		build(p<<1,l,mid,k),build(p<<1|1,mid+1,r,k);
		val[p]=val[p<<1]+val[p<<1|1];
	}
	void spread(int p,int l,int r)
	{
		if(add[p]==-1) return ;
		int mid=l+r>>1;
		add[p<<1]=add[p<<1|1]=add[p];
		val[p<<1]=add[p]*(mid-l+1),val[p<<1|1]=add[p]*(r-mid);
		add[p]=-1;//..careless 
	}
	void update(int p,int l,int r,int L,int R,int v)
	{
		if(L<=l&&R>=r)
		{
			val[p]=v*(r-l+1);
			add[p]=v;
			return ;
		}
		spread(p,l,r);
		int mid=l+r>>1;
		if(L<=mid) update(p<<1,l,mid,L,R,v);
		if(R>mid) update(p<<1|1,mid+1,r,L,R,v);
		val[p]=val[p<<1]+val[p<<1|1];
	}
	int ask(int p,int l,int r,int L,int R)
	{
		if(L<=l&&R>=r) return val[p];
		spread(p,l,r);
		int mid=l+r>>1,res=0;
		if(L<=mid) res+=ask(p<<1,l,mid,L,R);
		if(R>mid) res+=ask(p<<1|1,mid+1,r,L,R);
		return res;
	}
}t1;
struct F{int op,l,r;}q[N];
bool check(int x)
{
	t1.build(1,1,n,x);
	for(int i=1;i<=m;i++)
	{
		int op=q[i].op,l=q[i].l,r=q[i].r,num=t1.ask(1,1,n,l,r);
		if(l>=r) continue;
		if(num==r-l+1||num==0) continue;
		if(op==0) t1.update(1,1,n,l,r-num,0),t1.update(1,1,n,r-num+1,r,1);
		else t1.update(1,1,n,l,l+num-1,1),t1.update(1,1,n,l+num,r,0);
	}
//	printf("x=%d num=%d\n",x,t1.ask(1,1,n,1,n));
	return t1.ask(1,1,n,k,k)==1;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=m;i++) scanf("%d%d%d",&q[i].op,&q[i].l,&q[i].r);
		scanf("%d",&k);
		int l=1,r=n,ans;
		while(l<=r)
		{
			int mid=l+r>>1;
			if(check(mid)) ans=mid,l=mid+1;
			else r=mid-1;
		}
		printf("%d\n",ans);
	}
}

好像还有一种效率更高的线段树分裂的做法?

posted @ 2022-07-31 18:02  Freshair_qprt  阅读(36)  评论(0编辑  收藏  举报