人生不过一场呼吸。呼吸不停,则生命与思考不止。
绝世难题。
::::info[题意]
给出一个
共有
中位数:定义长为
多测,
::::
一个经典的转化是,对于一个数
显然一个右端点至多有一个对应的左端点,并且是最靠右的那个。接下来是一些记号:
那么对于一个
观察
::::info[证明
同时从上面我们可以看到,
观察
而显而易见的是每个
先考虑如何判定
::::info[情形
此时
::::info[情形
所以我们只需要在这个范围内寻找合法的
考虑对于一个固定的
现在考虑扫描序列的过程中对于所有
::::info[维护方法] 其实不是很容易。讲一下如何构造双半群信息。
先考虑
- 区间
h_x 加v 。 - 区间
w_x 加v 。 - 区间
w_x\leftarrow \max\{w_x,h_x\} 。
考虑设计信息二元组
- 信息之间的运算:
(w_1,h_1)\oplus (w_2,h_2)=(\max\{w_1,w_2\},\max\{h_1,h_2\}) 。 - 信息与标记之间的运算:
(w,h)\otimes (x,y,z)=(\max\{w+x,h+y\},h+z) 。
那么三种操作都可以用信息和标记之间的运算刻画。
容易证明
手推一下可以发现构造
那么就可以使用带懒标记的线段树维护了。
使用上述方法倒着扫一遍序列可以得到每个左端点的存在前缀。而对于一个时刻而言合法的区间一定是左右端点从小到大依次匹配过去。按照
认为
::::success[一份常数巨大但是比较简洁的实现]
#include <bits/stdc++.h>
#define eb emplace_back
template<class T> void read(T &x) {
x = 0; T f = 1; char c = getchar();
for (; c < 48 || c > 57; c = getchar()) if (c == '-') f = -1;
for (; c > 47 && c < 58; c = getchar()) x = (x << 3) + (x << 1) + c - 48;
x *= f;
}
template<class T> void write(T x) {
if (x > 9) write(x / 10); putchar(x % 10 + 48);
}
template<class T> void print(T x, char ed = '\n') {
if (x < 0) putchar('-'), x = -x; write(x), putchar(ed);
}
using namespace std; using ll = long long; const int N = 100005, I = -1e9;
int n, k, q, a[N], T, tl[N], tr[N], ans[N];
vector<tuple<int, int, int>> g[N]; vector<int> vl[N], vr[N];
struct M {
ll x, y, z; M(ll X = 0, ll Y = I, ll Z = 0) { x = X; y = Y; z = Z; }
M operator*(const M &_) const {
return M(x + _.x, max(y + _.x, z + _.y), z + _.z);
}
};
struct D {
ll h, s; D(ll H = I, ll S = 0) { h = H; s = S; }
D operator+(const D &_) const { return D(max(h, _.h), max(s, _.s)); }
D operator*(const M &_) const { return D(max(h + _.x, s + _.y), s + _.z); }
};
struct X {
ll x, y; X(ll a = 0, ll b = I) { x = a; y = b; }
X operator*(const X &_) const { return X(x + _.x, max(y + _.x, _.y)); }
};
struct Y {
ll h; Y(ll x = 0) { h = x; }
Y operator+(const Y &_) const { return Y(max(h, _.h)); }
Y operator*(const X &_) const { return Y(max(h + _.x, _.y)); }
};
template<class D, class M> struct SEG {
D s[N << 2]; M t[N << 2];
int ls(int x) { return x << 1; } int rs(int x) { return x << 1 | 1; }
void C(int x, M v) { s[x] = s[x] * v; t[x] = t[x] * v; }
void P(int x) { C(ls(x), t[x]); C(rs(x), t[x]); t[x] = M(); }
void B(int x, int l, int r, D e) {
t[x] = M(); if (l == r) return void(s[x] = e); int m = l + r >> 1;
B(ls(x), l, m, e); B(rs(x), m + 1, r, e); s[x] = s[ls(x)] + s[rs(x)];
}
void U(int x, int l, int r, int ql, int qr, M v) {
if (ql > qr) return; if (ql <= l && r <= qr) return C(x, v);
int m = l + r >> 1; P(x); if (ql <= m) U(ls(x), l, m, ql, qr, v);
if (qr > m) U(rs(x), m + 1, r, ql, qr, v); s[x] = s[ls(x)] + s[rs(x)];
}
int Q(int x, int l, int r, int v) {
if (s[x].h < v) return 0;
if (l == r) return l; int m = l + r >> 1; P(x);
return s[rs(x)].h < v ? Q(ls(x), l, m, v) : Q(rs(x), m + 1, r, v);
}
}; SEG<D, M> t1; SEG<Y, X> t2;
struct BIT {
int a[N]; void C() { memset(a, 0, sizeof a); }
void U(int x, int v) { for (; x <= n; x += x & -x) a[x] += v; }
void U(int l, int r, int v) { U(l, v); U(r + 1, -v); }
int Q(int x) { int r = 0; for (; x; x -= x & -x) r += a[x]; return r; }
} t3, t4;
void work(int *b) {
t1.B(1, 1, n, D()); t2.B(1, 1, n, Y());
for (int i = 1; i <= n; ++i) {
t1.U(1, 1, n, 1, a[i], M(1, I)); t1.U(1, 1, n, a[i] + 1, n, M(-1, I));
t1.U(1, 1, n, 1, a[i], M(0, I, 1));
t1.U(1, 1, n, a[i] + 1, n, M(0, I, -1));
if (i > k)
t1.U(1, 1, n, 1, a[i - k], M(0, -1, -1)),
t1.U(1, 1, n, a[i - k] + 1, n, M(0, 1, 1));
if (i == k) t1.U(1, 1, n, 1, n, M(0, 0));
t2.U(1, 1, n, 1, a[i], X(1)); t2.U(1, 1, n, a[i] + 1, n, X(-1));
b[i] = t1.Q(1, 1, n, 0);
if (i >= k) b[i] = max(b[i], t2.Q(1, 1, n, 1));
t1.U(1, 1, n, 1, b[i], M(I)); t2.U(1, 1, n, 1, b[i], X(I, 0));
}
}
void lzyqwq() {
read(n); read(k); read(q); for (int i = 1; i <= n; ++i) read(a[i]);
work(tr); reverse(a + 1, a + n + 1); work(tl); reverse(tl + 1, tl + n + 1);
for (int i = 1; i <= n; ++i) vl[tl[i]].eb(i), vr[tr[i]].eb(i);
for (int i = 1, l, r, x; i <= q; ++i)
read(l), read(r), read(x), g[x].eb(l, r, i);
for (int i = n; i >= 1; --i) {
for (int j : vl[i]) t3.U(j + 1, n, 1); vl[i].clear();
for (int j : vr[i]) t4.U(j, n, 1); vr[i].clear();
for (auto [l, r, j] : g[i]) ans[j] = max(t4.Q(r) - t3.Q(l), 0);
g[i].clear();
}
for (int i = 1; i <= q; ++i) print(ans[i]); t3.C(); t4.C();
}
int main() { for (read(T); T--;) lzyqwq(); return 0; }
::::