在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字。

分析

二分答案,
把二分出的ans与原序列比较,小于ans的数改为-1,大于ans的数改为1。
对于输入的每一个修改,用线段树来处理。
最后求出\(q\)位上的数是-1还是1,然后接着二分。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=100005;
using namespace std;
int a[N],n,m,re[N][4],k,ans,lazy[N*5],_0[N*5],_1[N*5];
int down(int v,int mid,int l,int r)
{
	if(lazy[v]==-1)
	{
		lazy[v*2+1]=lazy[v*2]=lazy[v];
		_0[v*2]=mid-l+1;
		_0[v*2+1]=r-(mid+1)+1;
		_1[v*2]=0;
		_1[v*2+1]=0;
	}
	if(lazy[v]==1)
	{
		lazy[v*2+1]=lazy[v*2]=lazy[v];
		_1[v*2]=mid-l+1;
		_1[v*2+1]=r-(mid+1)+1;
		_0[v*2]=0;
		_0[v*2+1]=0;
	}
	lazy[v]=0;
}
int put(int v,int l,int r,int x,int y)
{
	if(l==r)
	{
		if(y==-1)
			_0[v]=1;
				else _1[v]=1;
		return 0;
	}
	int mid=(l+r)/2;
	if(x<=mid)
		put(v*2,l,mid,x,y);
	else
		put(v*2+1,mid+1,r,x,y);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
}
int get(int v,int l,int r,int x,int y)
{
	if(l==x && r==y)
	{
		return _1[v];
	}
	int mid=(l+r)/2;
	down(v,mid,l,r);
	int o;
	if(y<=mid)
		o=get(v*2,l,mid,x,y);
	else
	if(x>mid)
		o=get(v*2+1,mid+1,r,x,y);
	else
		o=get(v*2,l,mid,x,mid)+get(v*2+1,mid+1,r,mid+1,y);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
	return o;
}
int change(int v,int l,int r,int x,int y,int value)
{
	if(y<x) return 0;
	int mid=(l+r)/2;
	if(l==x && r==y)
	{
		lazy[v]=value;
		if(value<0)
		{
			_0[v]=r-l+1;
			_1[v]=0;
		}
		else
		{
			_1[v]=r-l+1;
			_0[v]=0;	
		}
		return 0;
	}
	down(v,mid,l,r);
	if(y<=mid)
		change(v*2,l,mid,x,y,value);
	else
	if(x>mid)
		change(v*2+1,mid+1,r,x,y,value);
	else
		change(v*2,l,mid,x,mid,value),change(v*2+1,mid+1,r,mid+1,y,value);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
}
int find(int v,int l,int r,int x)
{
	if(l==r)
	{
		return _0[v];
	}
	int mid=(l+r)/2;
	down(v,mid,l,r);
	int o;
	if(x<=mid)
		o=find(v*2,l,mid,x);
	else
		o=find(v*2+1,mid+1,r,x);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
	return o;
}
bool check(int x)
{
	memset(lazy,0,sizeof(lazy));
	memset(_0,0,sizeof(_0));
	memset(_1,0,sizeof(_1));
	for(int i=1;i<=n;i++)
	{
		int g=a[i]<=x?-1:1;
		put(1,1,n,i,g);
	}
	for(int i=1;i<=m;i++)
	{
		int p1=get(1,1,n,re[i][2],re[i][3]);
		if(!re[i][1])
		{
			change(1,1,n,re[i][2],re[i][3]-p1,-1);
			change(1,1,n,re[i][3]-p1+1,re[i][3],1);
		}
		else
		{
			change(1,1,n,re[i][2],re[i][2]+p1-1,1);
			change(1,1,n,re[i][2]+p1,re[i][3],-1);	
		}
	}
	if(find(1,1,n,k))
		return true;
			else return false;
}
int main()
{
	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",&re[i][1],&re[i][2],&re[i][3]);
	}
	scanf("%d",&k);
	int l=1,r=n;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(check(mid))
		{
			r=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	printf("%d",l);
}

相关文章:

  • 2021-06-06
  • 2021-11-01
  • 2022-12-23
  • 2021-10-17
  • 2021-10-18
  • 2021-08-24
  • 2021-06-14
猜你喜欢
  • 2022-03-01
  • 2021-10-20
  • 2021-08-01
  • 2021-12-09
  • 2021-09-21
  • 2021-10-30
  • 2021-09-07
相关资源
相似解决方案