划分树模板题,敲上模板就ok了。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define MP make_pair #define LL long long #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; #define MID ((l+r)>>1) const int maxn = 100100; const int INF = 0x3f3f3f3f; struct KthNumber { int a[maxn], s[maxn], t[20][maxn], num[20][maxn]; void init(int n) { for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); s[i] = t[0][i] = a[i]; } sort(s+1, s+n+1); } void Build(int c, int l, int r) { int lm = MID-l+1, lp = l, rp = MID+1; for(int i = l; i <= MID; i ++) lm -= s[i] < s[MID]; for(int i = l; i <= r; i ++) { if(i == l) num[c][i] = 0; else num[c][i] = num[c][i - 1]; if(t[c][i] == s[MID]) { if(lm) { lm --; num[c][i] ++; t[c+1][lp++] = t[c][i]; } else t[c+1][rp++] = t[c][i]; } else if(t[c][i] < s[MID]) { num[c][i] ++; t[c+1][lp++] = t[c][i]; } else t[c+1][rp++] = t[c][i]; } if(l<r) Build(c+1, l, MID), Build(c+1, MID+1, r); } int Query(int c, int l, int r, int ql, int qr, int k) { if(l == r) return t[c][l]; int s, ss; if(l == ql) s = 0, ss = num[c][qr]; else s = num[c][ql-1], ss = num[c][qr]-num[c][ql-1]; if(k <= ss) return Query(c+1, l, MID, l+s, l+s+ss-1, k); else return Query(c+1, MID+1, r, MID+1+ql-l-s, MID+1+qr-l-s-ss, k-ss); } }sol; int main() { int n, m; while(scanf("%d%d", &n, &m) != EOF) { sol.init(n); sol.Build(0, 1, n); while(m --) { int l, r, k; scanf("%d%d%d", &l, &r, &k); printf("%d\n", sol.Query(0, 1, n, l, r, k)); } } }
poj 2104 K-th Number(划分树模板),布布扣,bubuko.com
原文地址:http://blog.csdn.net/ok_again/article/details/25301269