【HEOI2016】排序

题面

题解

这题好神仙啊。。。

我们二分这个位置上的数,

然后当\(val[i] \geq mid\)的位置设为\(1\),否则为\(0\)

这样一来,这道题就变成了一个\(01\)序列排序,所以就可以用线段树实现\(log_2n\)排序(区间和以及区间覆盖)

由于这个数列是\(1-n\)的全排列,所以二分出的结果就是答案。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);

inline int read()
{
	int data = 0, w = 1;
	char ch = getchar();
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(1e5 + 10);
int n, m, q, tree[maxn << 2], lazy[maxn << 2], a[maxn], opt[maxn], L[maxn], R[maxn];

#define son(i) ((root << 1) | (i))
inline void build(int x, int root = 1, int l = 1, int r = n)
{
	lazy[root] = 0;
	if(l == r) { tree[root] = (a[l] >= x); return; }
	int mid = (l + r) >> 1;
	build(x, son(0), l, mid);
	build(x, son(1), mid + 1, r);
	tree[root] = tree[son(0)] + tree[son(1)];
}

inline void pushdown(int root, int l, int r, int mid)
{
	if(l == r) lazy[root] = 0;
	if(!lazy[root]) return;
	lazy[son(0)] = lazy[son(1)] = lazy[root];
	if(lazy[root] == 1) tree[son(0)] = mid - l + 1, tree[son(1)] = r - mid;
	else tree[son(0)] = tree[son(1)] = 0;
	lazy[root] = 0;
}

inline void update(int ql, int qr, int val, int root = 1, int l = 1, int r = n)
{
	if(qr < l || r < ql) return;
	if(ql <= l && r <= qr) { tree[root] = val * (r - l + 1); lazy[root] = val ? 1 : -1; return; }
	int mid = (l + r) >> 1; pushdown(root, l, r, mid);
	update(ql, qr, val, son(0), l, mid);
	update(ql, qr, val, son(1), mid + 1, r);
	tree[root] = tree[son(0)] + tree[son(1)];
}

inline int query(int ql, int qr, int root = 1, int l = 1, int r = n)
{
	if(qr < l || r < ql) return 0;
	if(ql <= l && r <= qr) return tree[root];
	int mid = (l + r) >> 1; pushdown(root, l, r, mid);
	return query(ql, qr, son(0), l, mid) + query(ql, qr, son(1), mid + 1, r);
}

inline bool check(int mid)
{
	build(mid);
	for(RG int i = 1; i <= m; i++)
	{
		int cnt = query(L[i], R[i]);
		if(!opt[i])
			update(R[i] - cnt + 1, R[i], 1),
			update(L[i], R[i] - cnt, 0);
		else
			update(L[i], L[i] + cnt - 1, 1),
			update(L[i] + cnt, R[i], 0);
	}
	return query(q, q);
}

int main()
{
#ifndef ONLINE_JUDGE
	file(cpp);
#endif
	n = read(); m = read();
	for(RG int i = 1; i <= n; i++) a[i] = read();
	for(RG int i = 1; i <= m; i++) opt[i] = read(), L[i] = read(), R[i] = read();
	q = read(); int ans = 0;
	for(RG int l = 1, r = n, mid; l <= r;)
	{
		mid = (l + r) >> 1;
		if(check(mid)) ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	printf("%d\n", ans);
	return 0;
}
posted @ 2018-10-25 16:28  xgzc  阅读(171)  评论(0编辑  收藏  举报