给n个数,m次询问,每次询问一个区间,输出该区间中间大的值,中位数?划分树模版题。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100010; int tree[20][maxn], toleft[20][maxn], a[maxn]; void build(int l, int r, int dep) { if(l == r) return; int m = (l+r) >> 1; int tol = m-l+1; for(int i = l; i <= r; i++) { if(tree[dep][i] < a[m]) tol--; } int L = l, R = m+1; for(int i = l; i <= r; i++) { if(tree[dep][i] < a[m]) tree[dep+1][L++] = tree[dep][i]; else if(tree[dep][i] == a[m] && tol > 0) { tree[dep+1][L++] = tree[dep][i]; tol--; } else tree[dep+1][R++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l-1] + L-l; } build(l, m, dep+1); build(m+1, r, dep+1); } int query(int L, int R, int l, int r, int dep, int k) { if(l == r) return tree[dep][l]; int m = (L+R) >> 1; int cnt = toleft[dep][r]-toleft[dep][l-1]; if(cnt >= k) { int nextl = L + toleft[dep][l-1]-toleft[dep][L-1]; int nextr = nextl + cnt - 1; return query(L, m, nextl, nextr, dep+1, k); } else { int nextr = r + toleft[dep][R]-toleft[dep][r]; int nextl = nextr-(r-l-cnt); return query(m+1, R, nextl, nextr, dep+1, k-cnt); } } int main() { int n, cas = 1; while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; i++) { scanf("%d", &tree[0][i]); a[i] = tree[0][i]; } sort(a+1, a+n+1); int q; scanf("%d", &q); build(1, n, 0); printf("Case %d:\n", cas++); while(q--) { int l, r; scanf("%d %d", &l, &r); int m = (r-l)/2+1; printf("%d\n", query(1, n, l, r, 0, m)); } } return 0; }