HEOI2016/TJOI2016 排序

题目传送门

奇妙的题目


把操作离线下来,二分第\(q\)位置上的数\(x\),将排列中大于\(x\)的数记为\(1\),小于\(x\)的数记为\(0\),然后就可以很简单的用线段树维护每个操作
最后判断\(q\)位置上的数是否为\(1\)
时间复杂度\(O(n\log^2 n)\)

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define LL long long
#define ls p << 1
#define rs p << 1 | 1
#define mid ((l+r) >> 1)
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
struct zzz {
	int num1, num0;
}tree[100010 << 2];
struct hhh {
	bool opt; int l, r;
}que[100010];
int tag[100010 << 2];
int n, q, pos, a[100010], b[100010];
inline void up(int p) {
	tree[p].num0 = tree[ls].num0 + tree[rs].num0;
	tree[p].num1 = tree[ls].num1 + tree[rs].num1;
}
inline void down(int p) {
	if(tag[p] != -1) {
		if(!tag[p]) {
			tree[ls].num0 = tree[ls].num0 + tree[ls].num1;
			tree[ls].num1 = 0;
			tree[rs].num0 = tree[rs].num0 + tree[rs].num1;
			tree[rs].num1 = 0;
			tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
		}
		else {
			tree[ls].num1 = tree[ls].num0 + tree[ls].num1;
			tree[ls].num0 = 0;
			tree[rs].num1 = tree[rs].num0 + tree[rs].num1;
			tree[rs].num0 = 0;
			tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
		}
	}
}
void build(int l = 1, int r = n, int p = 1) {
	tag[p] = -1; tree[p].num0 = tree[p].num1 = 0;
	if(l == r) {
		if(a[l]) tree[p].num1 = 1;
		else tree[p].num0 = 1;
		return ;
	}
	build(l, mid, ls); build(mid+1, r, rs);
	up(p);
}
int query(int nl, int nr, int l = 1, int r = n, int p = 1) {
	if(nl <= l && nr >= r) return tree[p].num0;
	down(p);
	int ans = 0;
	if(nl <= mid) ans += query(nl, nr, l, mid, ls);
	if(nr > mid) ans += query(nl, nr, mid+1, r, rs);
	return ans;
}
void update(int nl, int nr, bool k, int l = 1, int r = n, int p = 1) {
	if(nl <= l && nr >= r) {
		if(!k) {
			tree[p].num0 = tree[p].num0 + tree[p].num1;
			tree[p].num1 = 0; tag[p] = k;
		}
		else {
			tree[p].num1 = tree[p].num0 + tree[p].num1;
			tree[p].num0 = 0; tag[p] = k;
		}
		return ;
	}
	down(p);
	if(nl <= mid) update(nl, nr, k, l, mid, ls);
	if(nr > mid) update(nl, nr, k, mid+1, r, rs);
	up(p);
}

bool check(int k) {
	build();
	for(int i = 1; i <= q; ++i) {
		int cnt = query(que[i].l, que[i].r);
		//注意区间全部为1和全部为0的情况
		if(cnt == 0) {
			update(que[i].l, que[i].r, 1); continue;
		}
		if(cnt == que[i].r-que[i].l+1) {
			update(que[i].l, que[i].r, 0); continue;
		}
		if(que[i].opt)
			update(que[i].l, que[i].r-cnt, 1),
			update(que[i].r-cnt+1, que[i].r, 0);
		else
			update(que[i].l, que[i].l+cnt-1, 0),
			update(que[i].l+cnt, que[i].r, 1);
	}
	return !query(pos, pos);
}
int main() {
	n = read(), q = read();
	for(int i = 1; i <= n; ++i) b[i] = read();
	for(int i = 1; i <= q; ++i)
		que[i].opt = read(), que[i].l = read(), que[i].r = read();
	pos = read();
	int l = 1, r = n, ans = 0;
	while(l <= r) {
		for(int i = 1; i <= n; ++i)
			if(b[i] >= mid) a[i] = 1;
			else a[i] = 0;
		if(check(mid)) ans = mid, l = mid+1;
		else r = mid - 1;
	}
	cout << ans;
    return 0;
}
posted @ 2019-11-14 11:13  MorsLin  阅读(111)  评论(0编辑  收藏  举报