离线算法(线段树+二分)只能过样例
查看原帖
离线算法(线段树+二分)只能过样例
141335
qwq2519楼主2021/8/31 16:13
#include<iostream>
#include<climits>
#include<cstdio>
#include<cstring>
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
#define bug puts("~~~~~~");
#define bugout(x) cout<<x<<endl;
using namespace std;
typedef long long lxl;
template<typename T>
inline T  max(T &a, T &b) {
	return a > b ? a : b;
}
template<typename T>
inline T  min(T &a, T &b) {
	return a < b ? a : b;
}

inline char gt() {
	static char buf[1 << 21], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename T>
inline void  read(T &x) {
	register char ch = gt();
	x = 0;
	int w(0);
	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
	w ? x = ~(x - 1) : x;
}
template <typename T>
inline void out(T x) {
	if(x < 0) x = -x, putchar('-');
	char ch[20];
	int num(0);
	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
	while(num) putchar(ch[num--]);
	putchar('\n');
}
const int N = 1e5 + 79;
int n, m, q;
int a[N];
struct opt {
	int op, l, r;
} p[N];

struct SegmentTree {
	int lc[N << 1], rc[N << 1], root, cnt;
	int lazy[N << 1], data[N << 1];

	inline void init() {
		cnt = 0;
		root = 0; //初始化 不能为1~~
		memset(lc, 0, sizeof lc);
		memset(lazy, 0xff, sizeof lazy);
		memset(rc, 0, sizeof rc);
		memset(data, 0, sizeof data);
	}
	inline void pushdown(int p, int L, int R) {
		if(lazy[p] == -1) return ;
		int mid(L + R >> 1);
		lazy[rc[p]] = lazy[lc[p]] = lazy[p];

		if(lazy[p]) {
			data[lc[p]] = mid - L + 1;
			data[rc[p]] = R - mid;
		} else data[lc[p]] = data[rc[p]] = 0;
		lazy[p] = 0;
	}


	inline void insert(int &p, int L, int R, int pos, int val) {
		if(!p) p = ++cnt;
		if(L == R) {
			data[p] = val;
			return ;
		}
		int mid(L + R >> 1);
		if(pos <= mid) insert(lc[p], L, mid, pos, val);
		else insert(rc[p], mid + 1, R, pos, val);
		data[p] = data[lc[p]] + data[rc[p]];
	}


	inline void change(int p, int L, int R, int ll, int rr, int val) {
       if(!p) return;
		if(ll <= L && rr >= R) {
			data[p] = val * (R - L + 1);
			lazy[p] = val;
			return ;
		}

		pushdown(p, L, R);
		int mid(L + R >> 1);
		if(ll <= mid) change(lc[p], L, mid, ll, rr, val);
		if(rr > mid) change(rc[p], mid + 1, R, ll, rr, val);
		data[p] = data[lc[p]] + data[rc[p]];
	}
	inline int query(int p, int L, int R, int ll, int rr) {
		if(!p) return 0;
		if(ll <= L && rr >= R) {
			return data[p];
		}
		pushdown(p, L, R);
		int mid(L + R >> 1), ans(0);
		if(ll <= mid) ans += query(lc[p], L, mid, ll, rr) ;
		if(rr > mid)    ans += query(rc[p], mid + 1, R, ll, rr);
		return ans;
	}
} S;

inline int check(int x) {

	S.init();

	rep(i, 1, n) {
		S.insert(S.root, 1, n, i, a[i] >= x);
	}
	rep(i, 1, m) {
		int cnt = S.query(S.root, 1, n, p[i].l, p[i].r);
		if(p[i].op == 0) {
			S.change(S.root, 1, n, p[i].r - cnt + 1, p[i].r, 1);
			S.change(S.root, 1, n, p[i].l, p[i].r - cnt , 0);
		} else {
			S.change(S.root, 1, n, p[i].l + cnt, p[i].r, 0);
			S.change(S.root, 1, n, p[i].l, p[i].l + cnt - 1, 1);
		}
	}
	return S.query(S.root, 1, n, q, q);
}




int main() {

	read(n);
	read(m);
	rep(i, 1, n) {
		read(a[i]);
	}
	rep(i, 1, m) {
		read(p[i].op);
		read(p[i].l);
		read(p[i].r);
	}

	read(q);
	
	int l = 1, r = n, mid, ans;
	while(l <= r) {
		mid = (l + r) >> 1;
		if(check(mid)) {
	         l=mid+1;
	         ans=mid;
		}
		else r=mid-1;
	}
    out(ans);
	return 0;
}
2021/8/31 16:13
加载中...