排序

/*
题目描述
在 20162016 年,佳媛姐姐喜欢上了数字序列。因而她经常研究关于序列的一些奇奇怪怪的问题,现在她在研究一个难题,需要你来帮助她。

这个难题是这样子的:给出一个 1 到 n 的排列,现在对这个排列序列进行 m 次局部排序,排序分为两种:
0 l r 表示将区间 [l,r][l,r] 的数字升序排序
1 l r 表示将区间 [l,r][l,r] 的数字降序排序
注意,这里是对下标在区间 [l,r][l,r] 内的数排序。
最后询问第 q 位置上的数字。

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

ac 5
*/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 10;
static int L[maxn], R[maxn], op[maxn];
static int n, m, k;
struct node
{
	int l, r;
	int sum, tag;//tag:区间标记为0或者为1
};
struct sgt_tree
{
	node t[maxn * 49];
	int a[maxn];
	void pushup(int u)
	{
		t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
	}
	void build(int u, int l, int r, int z)
	{
		t[u].l = l, t[u].r = r, t[u].tag = -1;
		if (l == r)
		{
			t[u].sum = (a[l] >= z);
			return;
		}
		int mid = (l + r) / 2;
		build(u << 1, l, mid, z);
		build(u << 1 | 1, mid + 1, r, z);
		pushup(u); t[u].tag = -1;
	}
	void pushdown(int u)
	{
		if (t[u].tag != -1)
		{
			auto& tt = t[u], & ll = t[u << 1], & rr = t[u << 1 | 1];
			ll.tag = rr.tag = tt.tag;
			ll.sum = (ll.r - ll.l + 1) * tt.tag;
			rr.sum = (rr.r - rr.l + 1) * tt.tag;

			tt.tag = -1;
		}
	}
	int sum(int u, int ql, int qr)
	{
		if (t[u].l > qr || t[u].r < ql)return 0;
		if (ql <= t[u].l && t[u].r <= qr)return t[u].sum;
		pushdown(u);
		return sum(u << 1, ql, qr) + sum(u << 1 | 1, ql, qr);
	}
	void update(int u, int ql, int qr, int v)
	{
		if (t[u].l > qr || t[u].r < ql)return;
		if (ql <= t[u].l && t[u].r <= qr)
		{
			t[u].sum = (t[u].r - t[u].l + 1) * v;
			t[u].tag = v;
			return;
		}
		pushdown(u);
		update(u << 1, ql, qr, v); update(u << 1 | 1, ql, qr, v);
		pushup(u);
	}
	int ask(int u, int p)
	{
		if (t[u].l == t[u].r)return t[u].sum;
		int mid = (t[u].l + t[u].r) >> 1;
		pushdown(u);
		if (p <= mid)return ask(u << 1, p);
		else return ask(u << 1 | 1, p);
	}
}sgt;
inline int read()
{
	char ch = getchar(); int x = 0;
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
	return x;
}
bool cek(int rs)
{
	sgt.build(1, 1, n, rs);
	for (int i = 1; i <= m; i++)
	{
		int z = sgt.sum(1, L[i], R[i]);
		if (op[i] == 0)//升序
		{
			sgt.update(1, R[i] - z + 1, R[i], 1);
			sgt.update(1, L[i], R[i] - z, 0);
		}
		else
		{
			sgt.update(1, L[i], L[i] + z - 1, 1);
			sgt.update(1, L[i] + z, R[i], 0);
		}
	}
	return sgt.ask(1, k);
}
int main()
{
	n = read(); m = read();
	for (int i = 1; i <= n; i++)sgt.a[i] = read();
	for (int i = 1; i <= m; i++) {
		op[i] = read(); L[i] = read(); R[i] = read();
	}
	k = read();

	int l = 1, r = n, ans = -1;
	while (l <= r)
	{
		int mid = (l + r) / 2;
		if (cek(mid))l = mid + 1, ans = mid;
		else r = mid - 1;
	}
	printf("%d\n", ans);
	return 0;
}
posted @ 2021-10-06 00:01  warmhearthhh  阅读(51)  评论(0)    收藏  举报