4552: [Tjoi2016&Heoi2016]排序

4552: [Tjoi2016&Heoi2016]排序

Time Limit: 60 Sec   Memory Limit: 256 MB
Submit: 509   Solved: 291
[ Submit][ Status][ Discuss]

Description

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

Input

输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
,1 <= m <= 10^5

Output

 输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

Sample Input

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

Sample Output

5

HINT

Source

[ Submit][ Status][ Discuss]



二分答案为ans,然后将原序列做一些修改

把原序列中小于ans的数字全部替换成0,把原序列中大于等于ans的数字全部替换成1

这样每个操作都能用线段树实现了

最后检查位置Q是否为1即可==

复杂度O(nlog^2n)


第一发边界没判WA了。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn = 1E5 + 10;
const int T = 4;

int n,m,Q,s[2],a[maxn],b[maxn],sum[maxn*T][2]
	,Mark[maxn*T],L[maxn],R[maxn],typ[maxn];

void Build(int o,int l,int r)
{
	if (l == r)
	{
		sum[o][b[l]] = 1;
		sum[o][b[l]^1] = 0;
		Mark[o] = -1;
		return;
	}
	Mark[o] = -1;
	int mid = (l + r) >> 1;
	Build(o<<1,l,mid);
	Build(o<<1|1,mid+1,r);
	for (int i = 0; i < 2; i++)
		sum[o][i] = sum[o<<1][i] + sum[o<<1|1][i];
}

void pushdown(int o,int l,int r)
{
	if (Mark[o] == -1) return;
	int mid = (l + r) >> 1,len = r - l + 1;
	sum[o][Mark[o]] = len; sum[o][Mark[o]^1] = 0;
	if (l == r) {Mark[o] = -1; return;}
	Mark[o<<1] = Mark[o]; 
	Mark[o<<1|1] = Mark[o];
	Mark[o] = -1;
}

void Modify(int o,int l,int r,int ml,int mr,int tp)
{
	if (ml <= l && r <= mr)
	{
		Mark[o] = tp;
		pushdown(o,l,r);
		return;
	}
	pushdown(o,l,r);
	int mid = (l + r) >> 1;
	if (ml <= mid) Modify(o<<1,l,mid,ml,mr,tp); else pushdown(o<<1,l,mid);
	if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,tp); else pushdown(o<<1|1,mid+1,r);
	for (int i = 0; i < 2; i++)
		sum[o][i] = sum[o<<1][i] + sum[o<<1|1][i];
}

void Query(int o,int l,int r,int ql,int qr)
{
	pushdown(o,l,r);
	if (ql <= l && r <= qr)
	{
		for (int i = 0; i < 2; i++)
			s[i] += sum[o][i];
		return;
	}
	int mid = (l + r) >> 1;
	if (ql <= mid) Query(o<<1,l,mid,ql,qr);
	if (qr > mid) Query(o<<1|1,mid+1,r,ql,qr);
}

bool Judge(int now)
{
	for (int i = 1; i <= n; i++)
		b[i] = (a[i] >= now)?1:0;
	Build(1,1,n);
	for (int i = 1; i <= m; i++)
	{
		memset(s,0,sizeof(s));
		Query(1,1,n,L[i],R[i]);
		int len = R[i] - L[i] + 1;
		if (!typ[i])
		{
			if (s[0])
				Modify(1,1,n,L[i],L[i] + s[0] - 1,0);
			if (s[0] < len)
				Modify(1,1,n,L[i] + s[0],R[i],1);
		}
		else
		{
			if (s[1])
				Modify(1,1,n,L[i],L[i] + s[1] - 1,1);
			if (s[1] < len)
				Modify(1,1,n,L[i] + s[1],R[i],0);
		}
	}
	memset(s,0,sizeof(s));
	Query(1,1,n,Q,Q);
	return s[1];
}

int getint()
{
	char ch = getchar();
	int ret = 0;
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9')
		ret = ret*10 + ch - '0',ch = getchar();
	return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	n = getint(); m = getint();
	for (int i = 1; i <= n; i++) a[i] = getint();
	for (int i = 1; i <= m; i++)
		typ[i] = getint(),L[i] = getint(),R[i] = getint();
	Q = getint();
	
	int l = 1,r = n;
	while (r - l > 1)
	{
		int mid = (l + r) >> 1;
		if (Judge(mid)) l = mid;
		else r = mid;
	}
	if (Judge(r)) cout << r;
	else cout << l;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值