首先看一下这个人的blog吧,讲的精炼 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html
然后再推荐一下这个人的blog:http://www.cnblogs.com/zinthos/p/3899565.html
这两个博客看了就差不多了。
自己说一下对代码的理解吧。
就是每一个数字开一个空间,然后每个空间用tot标号,最后tot就是总体开的数目。然后不同的线段树可能有相同的左儿子或者右二子(或者左=右,右=左),然后具体都是通过tot的储存值表现出来,大致就是这样吧。
代码挺裸的:
//看看会不会爆int! 或者绝对值问题。 #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define LL long long #define pb push_back #define mk make_pair #define fi first #define se second #define ALL(a) a.begin(), a.end() const int maxn = 100000 + 5; struct Segment{ int lb, rb; int cnt; Segment(int l = 0, int r = 0, int c = 0): lb(l), rb(r), cnt(c){} }s[maxn * 20]; int root[maxn]; int a[maxn]; int n, m, tot; int buildtree(int l, int r){ int k = tot++; if (l == r){ s[k] = Segment(0, 0, 0); return k; } int mid = (l + r) / 2; if (mid >= l) s[k].lb = buildtree(l, mid); else s[k].rb = buildtree(mid + 1, r); return k; } inline void push_up(int o){ s[o].cnt = s[s[o].lb].cnt + s[s[o].rb].cnt; } int update(int o, int l, int r, int pos, int val){ int k = tot++; s[k] = s[o]; if (l == r && l == pos){ s[k].cnt += val; return k; } int mid = (l + r) / 2; if (mid >= pos) s[k].lb = update(s[o].lb, l, mid, pos, val); else s[k].rb = update(s[o].rb, mid + 1, r, pos, val); push_up(k); return k; } int query(int o1, int o2, int l, int r, int num){ if (l == r) return l; int mid = (l + r) / 2; int res = s[s[o1].lb].cnt - s[s[o2].lb].cnt; if (res >= num) return query(s[o1].lb, s[o2].lb, l, mid, num); else return query(s[o1].rb, s[o2].rb, mid + 1, r, num - res); } int main(){ while (scanf("%d%d", &n, &m) == 2){ vector<int> v(n); for (int i = 1; i <= n; i++){ scanf("%d", a + i); v[i - 1] = a[i]; } sort(ALL(v)); v.erase(unique(ALL(v)), v.end()); for (int i = 1; i <= n; i++){ a[i] = lower_bound(ALL(v), a[i]) - v.begin() + 1; } tot = 0; int len = v.size(); root[0] = buildtree(1, len); for (int i = 1; i <= n; i++){ root[i] = update(root[i - 1], 1, len, a[i], 1); } for (int i = 1; i <= m; i++){ int l, r, num; scanf("%d%d%d", &l, &r, &num); int pos = query(root[r], root[l - 1], 1, len, num); printf("%d ", v[pos - 1]); } } return 0; }