划分树 + 二分
二分枚举第k小的数与h比较大小。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std; const int MAXN = 100100; struct Node { int l, r; }T[MAXN << 2]; int d[MAXN], s[MAXN], t[35][MAXN], tol[35][MAXN]; void build(int level, int rt, int l, int r) { int i; T[rt].l = l, T[rt].r = r; if(l == r) return; int mid = l + r >> 1; int lsame = mid - l + 1; for(i = l; i <= r; i ++) { if(t[level][i] < s[mid]) lsame --; } int Ll = l, Lr = mid, Rl = mid + 1, Rr = r; int Ltot = 0, Rtot = 0; for(i = l; i <= r; i ++) { if(i == l) tol[level][i] = 0; else tol[level][i] = tol[level][i - 1]; if(t[level][i] < s[mid]) { tol[level][i] ++; t[level + 1][Ll + Ltot ++] = t[level][i]; } else if(t[level][i] > s[mid]) { t[level + 1][Rl + Rtot ++] = t[level][i]; } else { if(lsame > 0) { lsame --; t[level + 1][Ll + Ltot ++] = t[level][i]; tol[level][i] ++; } else { t[level + 1][Rl + Rtot ++] = t[level][i]; } } } build(level + 1, rt << 1, Ll, Lr); build(level + 1, rt << 1 | 1, Rl, Rr); } int query(int level, int rt, int l, int r, int k) { if(l == r) return t[level][l]; int nl, nls; if(l == T[rt].l) nls = 0; else nls = tol[level][l - 1]; nl = tol[level][r] - nls; if(nl >= k) { return query(level + 1, rt << 1, T[rt].l + nls, T[rt].l + nl + nls - 1, k); } else { int mid = (T[rt].l + T[rt].r) >> 1; int nre = l - T[rt].l + 1 - nls; int nr = r - l + 1 - nl; return query(level + 1, rt << 1 | 1, mid + nre, mid + nr + nre - 1, k - nl); } } int BS(int r, int h, int L, int R) { int l = 0, mid; while(l < r) { mid = (l + r) >> 1; if(query(1, 1, L, R, mid) > h) r = mid ; else l = mid + 1; } return l; } int main() { int n, m, i, T, cas; scanf("%d", &T); for(cas = 1; cas <= T; cas ++) { scanf("%d%d", &n, &m); for(i = 1; i <= n; i ++) { //d[i] = 1; scanf("%d", &d[i]); t[1][i] = s[i] = d[i]; } sort(s + 1, s + n + 1); build(1, 1, 1, n); int l, r, h; printf("Case %d:\n", cas); while(m --) { scanf("%d%d%d", &l, &r, &h); l ++, r ++; if(query(1, 1, l, r, r - l + 1) <= h) printf("%d\n", r - l + 1); else if(query(1, 1, l, r, 1) > h) puts("0"); else{ int tt = BS(r - l + 1, h, l, r); //printf("%d\n", tt - 1); while(query(1, 1, l, r, tt) > h) { tt --; } printf("%d\n", tt); } } } return 0; }