Description
在2016年,佳媛姐姐喜欢上了数字序列。
因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。
这个难题是这样子的:
给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q位置上的数字。
Solution
本来是来学线段树的合并和分裂来着??
感觉是个套路吧。。。
考虑如果序列只要
0,1
0
,
1
,那么可以直接用线段树维护。
如果是个排列也是一样的,二分答案,将大于mid的看做1,小于等于mid的看做0即可。。
Source
/************************************************
* Au: Hany01
* Date: Mar 26th, 2018
* Prob: [BZOJ4552][TJOI2016&HEOI2016] 排序
* Email: hany01@foxmail.com
************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define fir first
#define sec second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read()
{
register int _, __; register char c_;
for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
const int maxn = 100005;
struct Qu
{
int t, l, r;
}q[maxn];
int n, m, tr[maxn << 2], tag[maxn << 2], a[maxn], M, fq;
#define lc (t << 1)
#define rc (lc | 1)
#define mid ((l + r) >> 1)
inline void pushdown(int t, int l, int r)
{
if (tag[t] == -1) return ;
tr[lc] = tag[t] * (mid - l + 1), tr[rc] = tag[t] * (r - mid);
tag[lc] = tag[rc] = tag[t], tag[t] = -1;
}
void build(int t, int l, int r)
{
tag[t] = -1;
if (l == r) {
tr[t] = a[l] > M;
return ;
}
build(lc, l, mid), build(rc, mid + 1, r),
tr[t] = tr[lc] + tr[rc];
}
int query(int t, int l, int r, int x, int y)
{
if (x <= l && r <= y) return tr[t];
pushdown(t, l, r);
if (y <= mid) return query(lc, l, mid, x, y);
if (mid < x) return query(rc, mid + 1, r, x, y);
return query(lc, l, mid, x, y) + query(rc, mid + 1, r, x, y);
}
void update(int t, int l, int r, int x, int y, int ne)
{
if (x > y) return ;//Pay attention !!!
if (x <= l && r <= y) {
tr[t] = ne * (r - l + 1), tag[t] = ne;
return ;
}
pushdown(t, l, r);
if (x <= mid) update(lc, l, mid, x, y, ne);
if (y > mid) update(rc, mid + 1, r, x, y, ne);
tr[t] = tr[lc] + tr[rc];
}
inline bool check()
{
register int sum;
build(1, 1, n);
For(i, 1, m)
{
sum = query(1, 1, n, q[i].l, q[i].r);
if (q[i].t) update(1, 1, n, q[i].l, q[i].l + sum - 1, 1), update(1, 1, n, q[i].l + sum, q[i].r, 0);
else update(1, 1, n, q[i].l, q[i].r - sum, 0), update(1, 1, n, q[i].r - sum + 1, q[i].r, 1);
}
return query(1, 1, n, fq, fq);
}
int main()
{
#ifdef hany01
File("bzoj4552");
#endif
//Input
n = read(), m = read();
For(i, 1, n) a[i] = read();
For(i, 1, m) q[i].t = read(), q[i].l = read(), q[i].r = read();
fq = read();
//Binary Search
static int L = 1, R = n;
while (L < R)
{
M = (L + R) >> 1;
if (check()) L = M + 1; else R = M;
}
printf("%d\n", L);
return 0;
}
//上邪,
//我欲与君相知,
//长命无绝衰。
//山无陵,
//江水为竭。
//冬雷震震,
//夏雨雪。
//天地合,
//乃敢与君绝。
// --佚名《上邪》