#include <bits/stdc++.h>
namespace SegmentTreeLazy {
/*******************************************************************************
* SegmentTree<Value, Extra, Traits> - segment tree class with lazy propagation, 0-indexed
* Default operations: minimal value on segment and addition on segment for int64_t type
* Use Traits<Value,Extra> for definition of:
* 1) neutral element for `Value`;
* 2) neutral element for `Extra`;
* 3) how should combine `Extra` with `Value`;
* 4) how should combine `Value` with `Value` (children to root);
* 5) how should combine `Extra` with `Extra`;
* See examples below: TraitsMinAdd<Value, Extra>
******************************************************************************/
/*******************************************************************************
* Traits for minimal value on segment.
* Get-query: get minimal value in segment [l, r]
* Update-query: add const to each value in segment [l, r]
******************************************************************************/
template<typename Value, typename Extra>
struct TraitsMinAdd {
// Definition of neutral element for `Value`:
static Value valueNeutral() { return std::numeric_limits<Value>::max(); }
// Definition of neutral element for `Extra`:
static Extra extraNeutral() { return Extra(0); }
// Definition of how should combine `Extra` with `Value`:
template<typename Node>
static Value getValue(const Node& src) {
return src.value() + src.extra();
}
// Definition of how should combine `Value` with `Value` (children to root):
template<typename NodeRoot, typename NodeLt, typename NodeRt>
static void pull(NodeRoot root, const NodeLt& lt, const NodeRt& rt) {
root.value() = std::min(getValue(lt), getValue(rt));
}
// Definition of how should combine `Extra` with `Extra`:
template<typename NodeDst, typename NodeSrc>
static void push(NodeDst dst, const NodeSrc& src) {
dst.extra() += src.extra();
}
};
/*******************************************************************************
* Additional traits, implemented below
******************************************************************************/
template<typename Value, typename Extra> struct TraitsMaxAdd;
/*******************************************************************************
* SegmentTree, see description above
******************************************************************************/
template<typename Value = int64_t, typename Extra = int64_t, typename Traits = TraitsMinAdd<Value, Extra> >
struct SegmentTree {
/*******************************************************************************
* Node class
******************************************************************************/
struct Node {
Value value;
Extra extra;
Node(Value value_ = Traits::valueNeutral(), Extra extra_ = Traits::extraNeutral())
: value(value_), extra(extra_) { }
Value getValue(int l, int r) const { return Traits::getValue(NodeWrapper<Node>(l, r, *this)); }
};
/*******************************************************************************
* NodeWrapper class
******************************************************************************/
template<typename NodeType>
struct NodeWrapper {
int l, r;
NodeType node;
NodeWrapper(int l_, int r_, NodeType node_)
: l(l_), r(r_), node(node_) { }
int left() const { return l; }
int right() const { return r; }
int mid() const { return (l+r)/2; }
int len() const { return r - l + 1; }
Value& value() { return node.value; }
Extra& extra() { return node.extra; }
const Value& value() const { return node.value; }
const Extra& extra() const { return node.extra; }
};
/*******************************************************************************
* SegmentTree public data: n - number of items, data - vector for nodes
******************************************************************************/
int n; std::vector<Node> data;
/*******************************************************************************
* Resize segment tree data to needed size
******************************************************************************/
void resize(int n_) {
n = n_;
data.assign(2 * n, Node());
}
/*******************************************************************************
* Lazy propagation from node to its children
******************************************************************************/
void push(int v, int l, int r, int m) {
if (data[v].extra != Traits::extraNeutral()) {
Traits::push(
NodeWrapper<Node&>(l, m, data[v+1]),
NodeWrapper<const Node&>(l, r, data[v])
);
Traits::push(
NodeWrapper<Node&>(m+1, r, data[v+2*(m-l+1)]),
NodeWrapper<const Node&>( l, r, data[v])
);
data[v].extra = Traits::extraNeutral();
}
}
/*******************************************************************************
* Update node using children values
******************************************************************************/
void pull(int v, int l, int r, int m) {
assert(data[v].extra == Traits::extraNeutral());
Traits::pull(
NodeWrapper<Node&>( l, r, data[v]),
NodeWrapper<const Node&>( l, m, data[v+1]),
NodeWrapper<const Node&>(m+1, r, data[v+2*(m-l+1)])
);
}
/*******************************************************************************
* Build segtree from array with given values
******************************************************************************/
template<typename T>
void build(const std::vector<T>& arr, const int v, const int tl, const int tr) {
if (tl == tr) {
data[v] = Node(arr[tl]);
} else {
const int tm = (tl + tr) / 2;
build(arr, v+1, tl, tm);
build(arr, v+2*(tm-tl+1), tm+1, tr);
pull(v, tl, tr, tm);
}
}
template<typename T>
void build(const std::vector<T>& arr) {
resize((int)arr.size());
build(arr, 0, 0, n-1);
}
/*******************************************************************************
* Get-query on range [ql, qr]
******************************************************************************/
Node get(int ql, int qr, const int v, const int tl, const int tr) {
if (ql == tl && qr == tr) {
return data[v];
} else {
int tm = (tl + tr) / 2;
push(v, tl, tr, tm);
Node ret;
if (qr <= tm) {
ret = get(ql, qr, v+1, tl, tm);
} else if (ql > tm) {
ret = get(ql, qr, v+2*(tm-tl+1), tm+1, tr);
} else {
const auto lt = get( ql, tm, v+1, tl, tm);
const auto rt = get(tm+1, qr, v+2*(tm-tl+1), tm+1, tr);
Traits::pull(
NodeWrapper<Node&>( ql, qr, ret),
NodeWrapper<const Node&>( ql, tm, lt),
NodeWrapper<const Node&>(tm+1, qr, rt)
);
}
pull(v, tl, tr, tm);
return ret;
}
}
Value get(const int ql, const int qr) { return get(ql, qr, 0, 0, n-1).getValue(ql, qr); }
/*******************************************************************************
* Update query on range [ql, qr] by extra
******************************************************************************/
void update(const int ql, const int qr, const Extra& extra, const int v, const int tl, const int tr) {
if (ql == tl && tr == qr) {
Traits::push(
NodeWrapper<Node&>(tl, tr, data[v]),
NodeWrapper<Node>(ql, qr, Node(Traits::valueNeutral(), extra))
);
} else {
int tm = (tl + tr) / 2;
push(v, tl, tr, tm);
if (qr <= tm) {
update(ql, qr, extra, v+1, tl, tm);
} else if (ql > tm) {
update(ql, qr, extra, v+2*(tm-tl+1),tm+1,tr);
} else {
update(ql, tm, extra, v+1, tl, tm);
update(tm+1, qr, extra, v+2*(tm-tl+1), tm+1, tr);
}
pull(v, tl, tr, tm);
}
}
void update(const int ql, const int qr, const Extra& extra) {
update(ql, qr, extra, 0, 0, n-1);
}
};
/*******************************************************************************
* Traits for maximal value on segment.
* Get-query: get maximal value in segment [l, r]
* Update-query: add const to each value in segment [l, r]
******************************************************************************/
template<typename Value, typename Extra>
struct TraitsMaxAdd {
// Definition of neutral element for `Value`:
static Value valueNeutral() { return std::numeric_limits<Value>::min(); }
// Definition of neutral element for `Extra`:
static Extra extraNeutral() { return Extra(0); }
// Definition of how should combine `Extra` with `Value`:
template<typename Node>
static Value getValue(const Node& src) {
return src.value() + src.extra();
}
// Definition of how should combine `Value` with `Value` (children to root):
template<typename NodeRoot, typename NodeLt, typename NodeRt>
static void pull(NodeRoot root, const NodeLt& lt, const NodeRt& rt) {
root.value() = std::max(getValue(lt), getValue(rt));
}
// Definition of how should combine `Extra` with `Extra`:
template<typename NodeDst, typename NodeSrc>
static void push(NodeDst dst, const NodeSrc& src) {
dst.extra() += src.extra();
}
};
}
int main() {
// Creating queries 1) arr[l..r] += x and 2) max(arr[l..r])
const int n = (int)1e6;
const int q = (int)1e6;
std::mt19937 gen;
std::uniform_int_distribution<int> dist(0,n-1);
std::vector<int> arr(n);
for (auto &it : arr) { it = dist(gen); }
std::vector<int> queryType(q), queryLeft(q), queryRight(q), queryExtra(q);
for (int i = 0; i < q; ++i) {
queryType[i] = 1 + dist(gen) % 2;
queryLeft[i] = dist(gen);
queryRight[i] = dist(gen);
if (queryLeft[i] > queryRight[i]) { std::swap(queryLeft[i], queryRight[i]); }
queryExtra[i] = dist(gen) - n / 2;
}
// Create SegmentTree
SegmentTreeLazy::SegmentTree<int64_t, int64_t, SegmentTreeLazy::TraitsMaxAdd<int64_t,int64_t>> segtree;
segtree.build(arr);
int64_t checkValue = 0;
for (int i = 0; i < q; ++i) {
if (queryType[i] == 1) {
segtree.update(queryLeft[i], queryRight[i], queryExtra[i]);
} else {
checkValue += segtree.get(queryLeft[i], queryRight[i]);
}
}
std::cout << "checkValue = " << checkValue << std::endl;
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CgpuYW1lc3BhY2UgU2VnbWVudFRyZWVMYXp5IHsKICAgIAogICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgICAqICBTZWdtZW50VHJlZTxWYWx1ZSwgRXh0cmEsIFRyYWl0cz4gLSBzZWdtZW50IHRyZWUgY2xhc3Mgd2l0aCBsYXp5IHByb3BhZ2F0aW9uLCAwLWluZGV4ZWQKICAgICAqICBEZWZhdWx0IG9wZXJhdGlvbnM6IG1pbmltYWwgdmFsdWUgb24gc2VnbWVudCBhbmQgYWRkaXRpb24gb24gc2VnbWVudCBmb3IgaW50NjRfdCB0eXBlCiAgICAgKiAgVXNlIFRyYWl0czxWYWx1ZSxFeHRyYT4gZm9yIGRlZmluaXRpb24gb2Y6CiAgICAgKiAgICAgIDEpICBuZXV0cmFsIGVsZW1lbnQgZm9yIGBWYWx1ZWA7CiAgICAgKiAgICAgIDIpICBuZXV0cmFsIGVsZW1lbnQgZm9yIGBFeHRyYWA7CiAgICAgKiAgICAgIDMpICBob3cgc2hvdWxkIGNvbWJpbmUgYEV4dHJhYCB3aXRoIGBWYWx1ZWA7CiAgICAgKiAgICAgIDQpICBob3cgc2hvdWxkIGNvbWJpbmUgYFZhbHVlYCB3aXRoIGBWYWx1ZWAgKGNoaWxkcmVuIHRvIHJvb3QpOwogICAgICogICAgICA1KSAgaG93IHNob3VsZCBjb21iaW5lIGBFeHRyYWAgd2l0aCBgRXh0cmFgOwogICAgICogIFNlZSBleGFtcGxlcyBiZWxvdzogVHJhaXRzTWluQWRkPFZhbHVlLCBFeHRyYT4KICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICAKICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAgICAgKiAgVHJhaXRzIGZvciBtaW5pbWFsIHZhbHVlIG9uIHNlZ21lbnQuIAogICAgICogIEdldC1xdWVyeTogICAgZ2V0IG1pbmltYWwgdmFsdWUgaW4gc2VnbWVudCBbbCwgcl0KICAgICAqICBVcGRhdGUtcXVlcnk6IGFkZCBjb25zdCB0byBlYWNoIHZhbHVlIGluIHNlZ21lbnQgW2wsIHJdCiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogICAgdGVtcGxhdGU8dHlwZW5hbWUgVmFsdWUsIHR5cGVuYW1lIEV4dHJhPgogICAgc3RydWN0IFRyYWl0c01pbkFkZCB7CiAgICAgICAgLy8gRGVmaW5pdGlvbiBvZiBuZXV0cmFsIGVsZW1lbnQgZm9yIGBWYWx1ZWA6CiAgICAgICAgc3RhdGljIFZhbHVlIHZhbHVlTmV1dHJhbCgpIHsgcmV0dXJuIHN0ZDo6bnVtZXJpY19saW1pdHM8VmFsdWU+OjptYXgoKTsgfQogICAgICAgIC8vIERlZmluaXRpb24gb2YgbmV1dHJhbCBlbGVtZW50IGZvciBgRXh0cmFgOgogICAgICAgIHN0YXRpYyBFeHRyYSBleHRyYU5ldXRyYWwoKSB7IHJldHVybiBFeHRyYSgwKTsgfQogICAgICAgIC8vIERlZmluaXRpb24gb2YgaG93IHNob3VsZCBjb21iaW5lIGBFeHRyYWAgd2l0aCBgVmFsdWVgOgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIE5vZGU+CiAgICAgICAgc3RhdGljIFZhbHVlIGdldFZhbHVlKGNvbnN0IE5vZGUmIHNyYykgewogICAgICAgICAgICByZXR1cm4gc3JjLnZhbHVlKCkgKyBzcmMuZXh0cmEoKTsKICAgICAgICB9CiAgICAgICAgLy8gRGVmaW5pdGlvbiBvZiBob3cgc2hvdWxkIGNvbWJpbmUgYFZhbHVlYCB3aXRoIGBWYWx1ZWAgKGNoaWxkcmVuIHRvIHJvb3QpOgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIE5vZGVSb290LCB0eXBlbmFtZSBOb2RlTHQsIHR5cGVuYW1lIE5vZGVSdD4KICAgICAgICBzdGF0aWMgdm9pZCBwdWxsKE5vZGVSb290IHJvb3QsIGNvbnN0IE5vZGVMdCYgbHQsIGNvbnN0IE5vZGVSdCYgcnQpIHsKICAgICAgICAgICAgcm9vdC52YWx1ZSgpID0gc3RkOjptaW4oZ2V0VmFsdWUobHQpLCBnZXRWYWx1ZShydCkpOwogICAgICAgIH0KICAgICAgICAvLyBEZWZpbml0aW9uIG9mIGhvdyBzaG91bGQgY29tYmluZSBgRXh0cmFgIHdpdGggYEV4dHJhYDoKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBOb2RlRHN0LCB0eXBlbmFtZSBOb2RlU3JjPgogICAgICAgIHN0YXRpYyB2b2lkIHB1c2goTm9kZURzdCBkc3QsIGNvbnN0IE5vZGVTcmMmIHNyYykgewogICAgICAgICAgICBkc3QuZXh0cmEoKSArPSBzcmMuZXh0cmEoKTsKICAgICAgICB9CiAgICB9OwogICAgCiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICogIEFkZGl0aW9uYWwgdHJhaXRzLCBpbXBsZW1lbnRlZCBiZWxvdyAKICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBWYWx1ZSwgdHlwZW5hbWUgRXh0cmE+ICBzdHJ1Y3QgVHJhaXRzTWF4QWRkOwogICAgCiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICogIFNlZ21lbnRUcmVlLCBzZWUgZGVzY3JpcHRpb24gYWJvdmUKICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBWYWx1ZSA9IGludDY0X3QsIHR5cGVuYW1lIEV4dHJhID0gaW50NjRfdCwgdHlwZW5hbWUgVHJhaXRzID0gVHJhaXRzTWluQWRkPFZhbHVlLCBFeHRyYT4gPgogICAgc3RydWN0IFNlZ21lbnRUcmVlIHsKICAgICAgICAKICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICAgICAqICBOb2RlIGNsYXNzCiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgICAgICBzdHJ1Y3QgTm9kZSB7CiAgICAgICAgICAgIFZhbHVlIHZhbHVlOwogICAgICAgICAgICAKICAgICAgICAgICAgRXh0cmEgZXh0cmE7CiAgICAgICAgICAgIAogICAgICAgICAgICBOb2RlKFZhbHVlIHZhbHVlXyA9IFRyYWl0czo6dmFsdWVOZXV0cmFsKCksIEV4dHJhIGV4dHJhXyA9IFRyYWl0czo6ZXh0cmFOZXV0cmFsKCkpCiAgICAgICAgICAgICAgICA6IHZhbHVlKHZhbHVlXyksIGV4dHJhKGV4dHJhXykgeyB9CiAgICAgICAgICAgIAogICAgICAgICAgICBWYWx1ZSBnZXRWYWx1ZShpbnQgbCwgaW50IHIpIGNvbnN0IHsgcmV0dXJuIFRyYWl0czo6Z2V0VmFsdWUoTm9kZVdyYXBwZXI8Tm9kZT4obCwgciwgKnRoaXMpKTsgfQogICAgICAgIH07CiAgICAgICAgCiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgICAgICAgKiAgTm9kZVdyYXBwZXIgY2xhc3MKICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIE5vZGVUeXBlPgogICAgICAgIHN0cnVjdCBOb2RlV3JhcHBlciB7CiAgICAgICAgICAgIGludCBsLCByOwogICAgICAgICAgICBOb2RlVHlwZSBub2RlOwogICAgICAgICAgICBOb2RlV3JhcHBlcihpbnQgbF8sIGludCByXywgTm9kZVR5cGUgbm9kZV8pCiAgICAgICAgICAgICAgICA6IGwobF8pLCByKHJfKSwgbm9kZShub2RlXykgeyB9CiAgICAgICAgICAgIGludCAgbGVmdCgpIGNvbnN0IHsgcmV0dXJuIGw7IH0KICAgICAgICAgICAgaW50IHJpZ2h0KCkgY29uc3QgeyByZXR1cm4gcjsgfQogICAgICAgICAgICBpbnQgICBtaWQoKSBjb25zdCB7IHJldHVybiAobCtyKS8yOyB9CiAgICAgICAgICAgIGludCAgIGxlbigpIGNvbnN0IHsgcmV0dXJuIHIgLSBsICsgMTsgfQogICAgICAgICAgICBWYWx1ZSYgdmFsdWUoKSB7IHJldHVybiBub2RlLnZhbHVlOyB9CiAgICAgICAgICAgIEV4dHJhJiBleHRyYSgpIHsgcmV0dXJuIG5vZGUuZXh0cmE7IH0KICAgICAgICAgICAgY29uc3QgVmFsdWUmIHZhbHVlKCkgY29uc3QgeyByZXR1cm4gbm9kZS52YWx1ZTsgfQogICAgICAgICAgICBjb25zdCBFeHRyYSYgZXh0cmEoKSBjb25zdCB7IHJldHVybiBub2RlLmV4dHJhOyB9CiAgICAgICAgfTsKICAgICAgICAKICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICAgICAqICBTZWdtZW50VHJlZSBwdWJsaWMgZGF0YTogbiAtIG51bWJlciBvZiBpdGVtcywgZGF0YSAtIHZlY3RvciBmb3Igbm9kZXMKICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogICAgICAgIGludCBuOyBzdGQ6OnZlY3RvcjxOb2RlPiBkYXRhOwogICAgICAgIAogICAgICAgIAogICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAgICAgICAgICogIFJlc2l6ZSBzZWdtZW50IHRyZWUgZGF0YSB0byBuZWVkZWQgc2l6ZQogICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICAgICAgdm9pZCByZXNpemUoaW50IG5fKSB7CiAgICAgICAgICAgIG4gPSBuXzsKICAgICAgICAgICAgZGF0YS5hc3NpZ24oMiAqIG4sIE5vZGUoKSk7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAgICAgICAgICogIExhenkgcHJvcGFnYXRpb24gZnJvbSBub2RlIHRvIGl0cyBjaGlsZHJlbgogICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICAgICAgdm9pZCBwdXNoKGludCB2LCBpbnQgbCwgaW50IHIsIGludCBtKSB7CiAgICAgICAgICAgIGlmIChkYXRhW3ZdLmV4dHJhICE9IFRyYWl0czo6ZXh0cmFOZXV0cmFsKCkpIHsKICAgICAgICAgICAgICAgIFRyYWl0czo6cHVzaCgKICAgICAgICAgICAgICAgICAgICBOb2RlV3JhcHBlcjxOb2RlJj4obCwgbSwgZGF0YVt2KzFdKSwgCiAgICAgICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Y29uc3QgTm9kZSY+KGwsIHIsIGRhdGFbdl0pCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgVHJhaXRzOjpwdXNoKAogICAgICAgICAgICAgICAgICAgIE5vZGVXcmFwcGVyPE5vZGUmPihtKzEsIHIsIGRhdGFbdisyKihtLWwrMSldKSwgCiAgICAgICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Y29uc3QgTm9kZSY+KCAgbCwgciwgZGF0YVt2XSkKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBkYXRhW3ZdLmV4dHJhID0gVHJhaXRzOjpleHRyYU5ldXRyYWwoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICAgICAqICBVcGRhdGUgbm9kZSB1c2luZyBjaGlsZHJlbiB2YWx1ZXMKICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogICAgICAgIHZvaWQgcHVsbChpbnQgdiwgaW50IGwsIGludCByLCBpbnQgbSkgewogICAgICAgICAgICBhc3NlcnQoZGF0YVt2XS5leHRyYSA9PSBUcmFpdHM6OmV4dHJhTmV1dHJhbCgpKTsKICAgICAgICAgICAgVHJhaXRzOjpwdWxsKAogICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Tm9kZSY+KCAgbCwgciwgZGF0YVt2XSksIAogICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Y29uc3QgTm9kZSY+KCAgbCwgbSwgZGF0YVt2KzFdKSwgCiAgICAgICAgICAgICAgICBOb2RlV3JhcHBlcjxjb25zdCBOb2RlJj4obSsxLCByLCBkYXRhW3YrMioobS1sKzEpXSkKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgICAgICAgKiAgQnVpbGQgc2VndHJlZSBmcm9tIGFycmF5IHdpdGggZ2l2ZW4gdmFsdWVzCiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgogICAgICAgIHZvaWQgYnVpbGQoY29uc3Qgc3RkOjp2ZWN0b3I8VD4mIGFyciwgY29uc3QgaW50IHYsIGNvbnN0IGludCB0bCwgY29uc3QgaW50IHRyKSB7CiAgICAgICAgICAgIGlmICh0bCA9PSB0cikgewogICAgICAgICAgICAgICAgZGF0YVt2XSA9IE5vZGUoYXJyW3RsXSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBjb25zdCBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwogICAgICAgICAgICAgICAgYnVpbGQoYXJyLCB2KzEsICAgdGwsIHRtKTsKICAgICAgICAgICAgICAgIGJ1aWxkKGFyciwgdisyKih0bS10bCsxKSwgdG0rMSwgdHIpOwogICAgICAgICAgICAgICAgcHVsbCh2LCB0bCwgdHIsIHRtKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgogICAgICAgIHZvaWQgYnVpbGQoY29uc3Qgc3RkOjp2ZWN0b3I8VD4mIGFycikgeyAKICAgICAgICAgICAgcmVzaXplKChpbnQpYXJyLnNpemUoKSk7CiAgICAgICAgICAgIGJ1aWxkKGFyciwgMCwgMCwgbi0xKTsKICAgICAgICB9CgogICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAgICAgICAgICogIEdldC1xdWVyeSBvbiByYW5nZSBbcWwsIHFyXQogICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCiAgICAgICAgTm9kZSBnZXQoaW50IHFsLCBpbnQgcXIsIGNvbnN0IGludCB2LCBjb25zdCBpbnQgdGwsIGNvbnN0IGludCB0cikgewogICAgICAgICAgICBpZiAocWwgPT0gdGwgJiYgcXIgPT0gdHIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBkYXRhW3ZdOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgaW50IHRtID0gKHRsICsgdHIpIC8gMjsKICAgICAgICAgICAgICAgIHB1c2godiwgdGwsIHRyLCB0bSk7CiAgICAgICAgICAgICAgICBOb2RlIHJldDsKICAgICAgICAgICAgICAgIGlmIChxciA8PSB0bSkgewogICAgICAgICAgICAgICAgICAgIHJldCA9IGdldChxbCwgcXIsIHYrMSwgICB0bCwgdG0pOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxbCA+IHRtKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0ID0gZ2V0KHFsLCBxciwgdisyKih0bS10bCsxKSwgdG0rMSwgdHIpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRvIGx0ID0gZ2V0KCAgcWwsIHRtLCB2KzEsICAgdGwsIHRtKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRvIHJ0ID0gZ2V0KHRtKzEsIHFyLCB2KzIqKHRtLXRsKzEpLCB0bSsxLCB0cik7CiAgICAgICAgICAgICAgICAgICAgVHJhaXRzOjpwdWxsKAogICAgICAgICAgICAgICAgICAgICAgICBOb2RlV3JhcHBlcjxOb2RlJj4oICBxbCwgcXIsIHJldCksIAogICAgICAgICAgICAgICAgICAgICAgICBOb2RlV3JhcHBlcjxjb25zdCBOb2RlJj4oICBxbCwgdG0sIGx0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIE5vZGVXcmFwcGVyPGNvbnN0IE5vZGUmPih0bSsxLCBxciwgcnQpCiAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHB1bGwodiwgdGwsIHRyLCB0bSk7CiAgICAgICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIFZhbHVlIGdldChjb25zdCBpbnQgcWwsIGNvbnN0IGludCBxcikgeyByZXR1cm4gZ2V0KHFsLCBxciwgMCwgMCwgbi0xKS5nZXRWYWx1ZShxbCwgcXIpOyB9CiAgICAgICAgCiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgICAgICAgKiAgVXBkYXRlIHF1ZXJ5IG9uIHJhbmdlIFtxbCwgcXJdIGJ5IGV4dHJhCiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgICAgICB2b2lkIHVwZGF0ZShjb25zdCBpbnQgcWwsIGNvbnN0IGludCBxciwgY29uc3QgRXh0cmEmIGV4dHJhLCBjb25zdCBpbnQgdiwgY29uc3QgaW50IHRsLCBjb25zdCBpbnQgdHIpIHsKICAgICAgICAgICAgaWYgKHFsID09IHRsICYmIHRyID09IHFyKSB7CiAgICAgICAgICAgICAgICBUcmFpdHM6OnB1c2goCiAgICAgICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Tm9kZSY+KHRsLCB0ciwgZGF0YVt2XSksCiAgICAgICAgICAgICAgICAgICAgTm9kZVdyYXBwZXI8Tm9kZT4ocWwsIHFyLCBOb2RlKFRyYWl0czo6dmFsdWVOZXV0cmFsKCksIGV4dHJhKSkKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwogICAgICAgICAgICAgICAgcHVzaCh2LCB0bCwgdHIsIHRtKTsKICAgICAgICAgICAgICAgIGlmIChxciA8PSB0bSkgewogICAgICAgICAgICAgICAgICAgIHVwZGF0ZShxbCwgcXIsIGV4dHJhLCB2KzEsIHRsLCB0bSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHFsID4gdG0pIHsKICAgICAgICAgICAgICAgICAgICB1cGRhdGUocWwsIHFyLCBleHRyYSwgdisyKih0bS10bCsxKSx0bSsxLHRyKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlKHFsLCB0bSwgZXh0cmEsIHYrMSwgICB0bCwgdG0pOwogICAgICAgICAgICAgICAgICAgIHVwZGF0ZSh0bSsxLCBxciwgZXh0cmEsIHYrMioodG0tdGwrMSksIHRtKzEsIHRyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHB1bGwodiwgdGwsIHRyLCB0bSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHZvaWQgdXBkYXRlKGNvbnN0IGludCBxbCwgY29uc3QgaW50IHFyLCBjb25zdCBFeHRyYSYgZXh0cmEpIHsKICAgICAgICAgICAgdXBkYXRlKHFsLCBxciwgZXh0cmEsIDAsIDAsIG4tMSk7IAogICAgICAgIH0KCiAgICB9OwogICAgCiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICAgICogIFRyYWl0cyBmb3IgbWF4aW1hbCB2YWx1ZSBvbiBzZWdtZW50LiAKICAgICAqICBHZXQtcXVlcnk6ICAgIGdldCBtYXhpbWFsIHZhbHVlIGluIHNlZ21lbnQgW2wsIHJdCiAgICAgKiAgVXBkYXRlLXF1ZXJ5OiBhZGQgY29uc3QgdG8gZWFjaCB2YWx1ZSBpbiBzZWdtZW50IFtsLCByXQogICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgIHRlbXBsYXRlPHR5cGVuYW1lIFZhbHVlLCB0eXBlbmFtZSBFeHRyYT4KICAgIHN0cnVjdCBUcmFpdHNNYXhBZGQgewogICAgICAgIC8vIERlZmluaXRpb24gb2YgbmV1dHJhbCBlbGVtZW50IGZvciBgVmFsdWVgOgogICAgICAgIHN0YXRpYyBWYWx1ZSB2YWx1ZU5ldXRyYWwoKSB7IHJldHVybiBzdGQ6Om51bWVyaWNfbGltaXRzPFZhbHVlPjo6bWluKCk7IH0KICAgICAgICAvLyBEZWZpbml0aW9uIG9mIG5ldXRyYWwgZWxlbWVudCBmb3IgYEV4dHJhYDoKICAgICAgICBzdGF0aWMgRXh0cmEgZXh0cmFOZXV0cmFsKCkgeyByZXR1cm4gRXh0cmEoMCk7IH0KICAgICAgICAvLyBEZWZpbml0aW9uIG9mIGhvdyBzaG91bGQgY29tYmluZSBgRXh0cmFgIHdpdGggYFZhbHVlYDoKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBOb2RlPgogICAgICAgIHN0YXRpYyBWYWx1ZSBnZXRWYWx1ZShjb25zdCBOb2RlJiBzcmMpIHsKICAgICAgICAgICAgcmV0dXJuIHNyYy52YWx1ZSgpICsgc3JjLmV4dHJhKCk7CiAgICAgICAgfQogICAgICAgIC8vIERlZmluaXRpb24gb2YgaG93IHNob3VsZCBjb21iaW5lIGBWYWx1ZWAgd2l0aCBgVmFsdWVgIChjaGlsZHJlbiB0byByb290KToKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBOb2RlUm9vdCwgdHlwZW5hbWUgTm9kZUx0LCB0eXBlbmFtZSBOb2RlUnQ+CiAgICAgICAgc3RhdGljIHZvaWQgcHVsbChOb2RlUm9vdCByb290LCBjb25zdCBOb2RlTHQmIGx0LCBjb25zdCBOb2RlUnQmIHJ0KSB7CiAgICAgICAgICAgIHJvb3QudmFsdWUoKSA9IHN0ZDo6bWF4KGdldFZhbHVlKGx0KSwgZ2V0VmFsdWUocnQpKTsKICAgICAgICB9CiAgICAgICAgLy8gRGVmaW5pdGlvbiBvZiBob3cgc2hvdWxkIGNvbWJpbmUgYEV4dHJhYCB3aXRoIGBFeHRyYWA6CiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgTm9kZURzdCwgdHlwZW5hbWUgTm9kZVNyYz4KICAgICAgICBzdGF0aWMgdm9pZCBwdXNoKE5vZGVEc3QgZHN0LCBjb25zdCBOb2RlU3JjJiBzcmMpIHsKICAgICAgICAgICAgZHN0LmV4dHJhKCkgKz0gc3JjLmV4dHJhKCk7CiAgICAgICAgfQogICAgfTsgICAKfQoKaW50IG1haW4oKSB7CiAgICAvLyBDcmVhdGluZyBxdWVyaWVzIDEpIGFycltsLi5yXSArPSB4IGFuZCAyKSBtYXgoYXJyW2wuLnJdKQogICAgY29uc3QgaW50IG4gPSAoaW50KTFlNjsKICAgIGNvbnN0IGludCBxID0gKGludCkxZTY7CiAgICBzdGQ6Om10MTk5MzcgZ2VuOwogICAgc3RkOjp1bmlmb3JtX2ludF9kaXN0cmlidXRpb248aW50PiBkaXN0KDAsbi0xKTsKICAgIHN0ZDo6dmVjdG9yPGludD4gYXJyKG4pOwogICAgZm9yIChhdXRvICZpdCA6IGFycikgeyBpdCA9IGRpc3QoZ2VuKTsgfQogICAgc3RkOjp2ZWN0b3I8aW50PiBxdWVyeVR5cGUocSksIHF1ZXJ5TGVmdChxKSwgcXVlcnlSaWdodChxKSwgcXVlcnlFeHRyYShxKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcTsgKytpKSB7CiAgICAgICAgcXVlcnlUeXBlW2ldID0gMSArIGRpc3QoZ2VuKSAlIDI7CiAgICAgICAgcXVlcnlMZWZ0W2ldID0gZGlzdChnZW4pOwogICAgICAgIHF1ZXJ5UmlnaHRbaV0gPSBkaXN0KGdlbik7CiAgICAgICAgaWYgKHF1ZXJ5TGVmdFtpXSA+IHF1ZXJ5UmlnaHRbaV0pIHsgc3RkOjpzd2FwKHF1ZXJ5TGVmdFtpXSwgcXVlcnlSaWdodFtpXSk7IH0KICAgICAgICBxdWVyeUV4dHJhW2ldID0gZGlzdChnZW4pIC0gbiAvIDI7CiAgICB9CiAgICAvLyBDcmVhdGUgU2VnbWVudFRyZWUKICAgIFNlZ21lbnRUcmVlTGF6eTo6U2VnbWVudFRyZWU8aW50NjRfdCwgaW50NjRfdCwgU2VnbWVudFRyZWVMYXp5OjpUcmFpdHNNYXhBZGQ8aW50NjRfdCxpbnQ2NF90Pj4gc2VndHJlZTsKICAgIHNlZ3RyZWUuYnVpbGQoYXJyKTsKICAgIGludDY0X3QgY2hlY2tWYWx1ZSA9IDA7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHE7ICsraSkgewogICAgICAgIGlmIChxdWVyeVR5cGVbaV0gPT0gMSkgewogICAgICAgICAgICBzZWd0cmVlLnVwZGF0ZShxdWVyeUxlZnRbaV0sIHF1ZXJ5UmlnaHRbaV0sIHF1ZXJ5RXh0cmFbaV0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNoZWNrVmFsdWUgKz0gc2VndHJlZS5nZXQocXVlcnlMZWZ0W2ldLCBxdWVyeVJpZ2h0W2ldKTsKICAgICAgICB9CiAgICB9CiAgICBzdGQ6OmNvdXQgPDwgImNoZWNrVmFsdWUgPSAiIDw8IGNoZWNrVmFsdWUgPDwgc3RkOjplbmRsOwogICAgcmV0dXJuIDA7Cn0=