持続可能なノートのセグメントツリーの前提を学びます
持続性があり、まとめたデータ構造と呼ばれる、と彼らはまた、いくつかの機能している能力であるバージョン履歴を保存し、そして今日は永続セグメントツリーは歴史的なバージョンを保持するデータ構造であると言うことができます
アルゴリズムの内容
競争のポイントは、使用する必要があります
空間1、データ範囲の使用に注意し、大消費の持続セグメント・ツリーであってもよいです
2、ゾーンの問題のための持続セグメントツリーを解消することができるが、基本的な形が異なるコードに似ている、我々は原則とコードの意味の木の会長を習得する必要があります
k個のセグメントツリーは少し大きな問題を話す永続求めることができます
永続セグメントツリーは、より一般的な用語を選択する私たちがここにいる、たくさんのことを維持することができます(私のような人々のためのアルゴリズムは、それ自体の重量を量る見ることは非常に困難です)。、タイムスタンプを保持するためにあらゆる編集を問題を考えてみましょう、そして我々は通常のセグメントツリーは、当社のニーズを満たしていないことは明らかである、タイムスタンプ上の問題の範囲を各アクセスをお願いします、我々は考えることができます書き込み永続化、単一ポイントに変更した場合は、その後、各変更が変更されます\(LOGN \) 、思考の変化をノードを、私たちはよりオープンの同等変更することができます\(LOGNを\)変更を保存するには、ノードの後に、これらの値他のノード変わらないので、私たちは、これらのノードを共有することができます。
共通ノード?あなたは何を意味するか、あなたは図を参照することができます(問題バレーピックへロス・ソリューション、本当に私が描きたくありません)
定義:オレンジフロント変更が、唯一の青[1,4]、[3,4]、[4,4]のための新たなポイントを変更しています
我々は発見したオレンジ色の[1,4]、青[1,4]共有[1,2]この時点で、[1,2]もちろんのサブツリーは、行うことができます言うまでもなく、我々はできるように、永続操作が、このような問題は、彼らは状況の方法をそれぞれのバージョンを知る方法はありますか?私たちは、のバージョンから簡単にフィードバックできるように、ノード数を保持するために、配列を使用する必要があります
このような状況を解決した後、我々はこの質問、分析検討し\(k個の\を)で、我々は検討する必要がある大きなものの前に([L、R] \ \ ) あなたの最初のを探して間隔\(k個\)大規模な、この\([L、R] \ ) 、出てくることが、実際には答えも準備行う方法セクション、あなたはここで分析し、プレフィックスとコンテンツメンテナンス間隔では、それが何を意味するのでしょうか?我々数に対する各リーフノードは、各番号のように含まれる間隔の数であり、重量ツリーラインは、そこ毎にある最初の番号と接頭辞、およびバージョンがあるので、[(\ 1、L] \)は、セグメントツリーは永続的であってもよいし、次いで\([1]、[R]は\ ) 我々が使用しているため、セグメントツリーは永続的であることができるされ、ちょっとプレフィックスおよび成果を行う、それは常にバージョンではありません会いプレフィックスと、それの性質を?もちろん、私たちが聞きたいことを、満たす\([L、R] \ ) のセクション\(k個\)大、我々が使用することができます\([1.R] - [1、L - 1] \)ので、私たちのです\([L、R] \ ) aが
間隔の要件を満たして、私たちの最初会いしましょう\(k個\)大規模な要件を、我々は今得ていると仮定し\([L、R]を\ ) まず求めて、ツリーラインの重さのこのバージョンを\(kは\ )大、我々は左のサブツリーを検討し、数が等しい以上であることがわかった(k個の\を)\、それは左にそれ、私たちの答えは明らかです。より少ない場合には、\(k個\)は、それが明確であることを、私たちの答えの権利は、あなたがWangyoubianzouをよ、しかし、注意してたときにWangyoubianzou私たちの最初の\(k個\)ビッグになり(k個の\を)\ -左サブツリー(\([1は、MID] \) )数に含まれ、描画は自分のを理解することができます
これは、我々はコードを書くことができます
Kは、コードセグメントツリー展示の持続性に大きな需要があってもよいです
そして、貢献があるとして、ツリーライン、
//#define fre yes
#include <cstdio>
const int N = 1000005;
int T[N];
struct Node {
int l, r, interval;
} tree[N << 5];
int cnt; //点的个数
void build(int l, int r) {
int rt = ++cnt;
tree[rt].l = l;
tree[rt].r = r;
tree[rt].interval = 0;
if(l == r) return ;
int mid = (l + r) >> 1;
build(l, mid);
build(mid + 1, r);
}
int main() {
build(1, m);
}
そして、シングルポイントの変更
int update(int pre, int l, int r, int x) { //update(T[g], 1, m, x) //g代表哪次版本
int rt = ++cnt;
tree[rt].l = tree[pre].l;
tree[rt].r = tree[prt].r;
tree[rt].interval = tree[pre].interval;
if(l == r) return rt;
int mid = (l + r) >> 1;
if(mid >= x) tree[rt].l = (tree[pre].l, l, mid, x);
else tree[rt].r = (tree[pre].r, mid + 1, r, x);
return rt;
}
お問い合わせの単一のポイント
int query(int u, int v, int l, int r, int x) {
if(l == r) return l;
int t = tree[tree[v].l] - tree[tree[u].l];
int mid = (l + r) >> 1;
if(t >= x) return query(tree[u].l, tree[v].l, l, mid, x);
else return query(tree[u].r, tree[v].r, mid + 1, r, x - t);
}
そして最後に例置く羅区P3834を
完全なコード
//#define fre yes
#include <cstdio>
#include <algorithm>
const int N = 200005;
int a[N], b[N], T[N];
struct Node {
int l, r, sum;
} tree[N << 5];
int cnt;
void build(int l, int r) {
int rt = ++cnt;
tree[rt].l = l;
tree[rt].r = r;
tree[rt].sum = 0;
if(l == r) return ;
int mid = (l + r) >> 1;
build(l, mid);
build(mid + 1, r);
}
int update(int pre, int l, int r, int x) {
int rt = ++cnt;
tree[rt].l = tree[pre].l;
tree[rt].r = tree[pre].r;
tree[rt].sum = tree[pre].sum + 1;
if(l == r) return rt;
int mid = (l + r) >> 1;
if(mid >= x) tree[rt].l = update(tree[pre].l, l, mid, x);
else tree[rt].r = update(tree[pre].r, mid + 1, r, x);
return rt;
}
int query(int u, int v, int l, int r, int x) {
if(l == r) return l;
int sum = tree[tree[v].l].sum - tree[tree[u].l].sum;
int mid = (l + r) >> 1;
if(sum >= x) return query(tree[u].l, tree[v].l, l, mid, x);
else return query(tree[u].r, tree[v].r, mid + 1, r, x - sum);
}
int main() {
static int n, q;
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &a[i]);
b[i] = a[i];
}
std::sort(b + 1, b + 1 + n);
int m = std::unique(b + 1, b + 1 + n) - b - 1;
T[0] = 0;
build(1, m);
for (int i = 1; i <= n; i++) {
int t = std::lower_bound(b + 1, b + 1 + m, a[i]) - b;
T[i] = update(T[i - 1], 1, m, t);
}
for (int i = 1; i <= q; i++) {
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
int t = query(T[x - 1], T[y], 1, m, z);
printf("%d\n", b[t]);
} return 0;
}