/* package whatever; // don't place package name! */
import java.util.* ;
import java.lang.* ;
import java.io.* ;
/**
* Created by green on 28.11.15.
*/
import java.security.Key ;
/**
* Created by green on 26.11.15.
*/
interface SegmentedArray< T> {
/**
* <p>Get value by element index</p>
* @param index index of element.
* @return Value of element with specified index.
*/
T get( int index) ;
/**
* <p>Set the same value for all elements in the specified index range</p>
* @param start the beginning index, inclusive.
* @param end the ending index, exclusive.
* @param value value for.
*/
void set( int start, int end, T value) ;
/**
* <p>Returns the index within this array of the first occurrence of the specified value,
* starting at the specified index. If no such value of k exists, then -1 is returned.</p>
* @param value the T-based value for which to search.
* @param fromIndex the index from which to start the search.
* @return the index within this array of the first occurrence of the element with specified value,
* starting at the specified index.
*/
int indexOf( T value, int fromIndex) ;
/**
* <p>Find minimum value in the specified indexes range</p>
* @param start the beginning index, inclusive.
* @param end the ending index, exclusive.
* @return Minimum value.
*/
T minValue( int start, int end) ;
}
class CT < Value extends Comparable< Value>> implements SegmentedArray< Value> {
private class Node {
Value value;
int l, r;
Node left, right, father;
public Node ( Value value, Node father, int l, int r) {
this .value = value;
this .left = this .right = null ;
this .father = father;
this .l = l; this .r = r;
}
}
private Node root;
private Node add ( Node node,Value value, Node father, int l, int r) {
if ( node == null ) {
Node newnode = new Node( value,father, l , r) ;
return newnode;
}
//int compareResultl = l.compareTo(node.l);
//int compareResultr = r.compareTo(node.r);
if ( l > node.r ) {
node.right = add( node.right , value, node, l, r) ;
} else if ( r < node.l ) {
node.left = add( node.left , value, node, l, r) ;
} else if ( l >= node.l && r <= node.r ) {
if ( l == node.l && r == node.r ) {
node.value = value;
return node;
} else if ( l == node.l ) {
node.right = add( node.right , node.value , node, r+ 1 , node.r ) ;
node.value = value;
node.r = r;
} else if ( r == node.r ) {
node.left = add( node.left , node.value , node, node.l , l- 1 ) ;
node.value = value;
node.l = l;
} else {
Node newnode = new Node( value,father, l , r) ;
newnode.left = node.left ;
newnode.right = node.right ;
newnode.left = add( newnode.left , node.value , newnode, node.l , l- 1 ) ;
newnode.right = add( newnode.right , node.value , newnode, r+ 1 , node.r ) ;
node = newnode;
}
} else if ( l < node.l && r > node.r ) {
node.value = value;
node.l = l;
node.r = r;
node.left = delete( node.left , l, false ) ;
node.right = delete( node.right , r, true ) ;
} else if ( l < node.l ) {
if ( r == node.r ) {
node.value = value;
node.l = l;
node.left = delete( node.left , l, false ) ;
} else {
node = add( node, node.value , father, r+ 1 , node.r ) ;
node = add( node, value, father, l, r) ;
}
} else if ( r > node.r ) {
if ( l == node.l ) {
node.value = value;
node.r = r;
node.right = delete( node.right , r, true ) ;
} else {
node = add( node, node.value , father, node.l , l - 1 ) ;
node = add( node, value, father, l, r) ;
}
}
return node;
}
public void set( int l, int r, Value value) {
root = add( root, value, null , l, r) ;
}
private Node delete
( Node node,
int d,
Boolean side
) { if ( node == null ) return null ;
if ( d < node.r && d > node.l ) {
node = add( node, node.value , node.father , node.l , d - 1 ) ;
node = delete( node, d, side) ;
} else if ( d < node.l ) {
if ( side)
node.left = delete( node.left , d, side) ;
else {
node = node.left ;
node = delete( node, d, side) ;
}
} else if ( d > node.r ) {
if ( side) {
node = node.right ;
node = delete( node, d, side) ;
} else
node.right = delete( node.right , d, side) ;
} else if ( d == node.r ) {
if ( side) { node = node.right ; } else { node.right = null ; node.r = d - 1 ; }
} else if ( d == node.l ) {
if ( side) { node.left = null ; node.l = d + 1 ; } else { node = node.left ; }
}
return node;
}
private Value get( Node node, int index) {
if ( node == null ) return null ;
if ( index > node.r )
return get( node.right , index) ;
else if ( index < node.l )
return get( node.left , index) ;
else
return node.value ;
}
public Value get( int index) {
return get( root, index) ;
}
private Value minimum( Value x, Value y) {
if ( x == null && y == null ) return null ;
else if ( x == null ) return y;
else if ( y == null ) return x;
else {
if ( x.compareTo ( y) == 1 ) return y;
else return x;
}
}
private Value min( Node node, int start, int end) {
if ( node == null ) return null ;
if ( end < node.l ) {
return min( node.left , start, end) ;
} else if ( start > node.r ) {
return min( node.right , start, end) ;
} else {
Value v1 = null , v2 = null ;
if ( start < node.l ) v1 = min( node.left , start, end) ;
if ( end > node.r ) v2 = min( node.right , start, end) ;
return minimum( v2, minimum( node.value , v1) ) ;
}
}
public Value minValue( int start, int end) {
return min( root, start, end) ;
}
private Integer indexOf
( Node node, Value value,
int index
) { if ( node == null ) return null ;
if ( index <= node.r ) {
if ( index < node.l ) {
v = indexOf( node.left , value, index) ;
if ( v != null ) return v;
}
if ( value
== node.
value ) return Math .
max ( node.
l , index
) ; v = indexOf( node.right , value, index) ;
if ( v != null ) return v;
}
return indexOf( node.right , value, index) ;
}
public int indexOf( Value value, int index) {
return indexOf( root, value, index) ;
}
private void print( Node node, int level) {
if ( node != null ) {
print( node.right ,level+ 1 ) ;
for ( int i= 0 ; i< level; i++ ) {
}
System .
out .
println ( node.
l + "-" + node.
r + "->" + node.
value ) ; print( node.left ,level+ 1 ) ;
}
}
public void print( ) {
print( root,0 ) ;
}
}
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
{
CT< Integer> tree = new CT<> ( ) ;
long start, end;
tree.set ( 50 , 4566 , 14 ) ;
//tree.set(130, 740, 29012);
//tree.set(1000, 1084, -2);
//tree.set(3006, 3070, 51);
end
= System .
nanoTime ( ) ; //tree.set(50, 4566, 14); System .
out .
println ( "Первый Set в BitSegmentedArray отрабатывает за " + ( end
- start
) + " нс." ) ;
System .
out .
println ( "Get в BitSegmentedArray отрабатывает за " + ( end
- start
) + " нс." ) ;
tree.set ( 76 , 830 , 1 ) ;
System .
out .
println ( "Второй Set в BitSegmentedArray отрабатывает за " + ( end
- start
) + " нс." ) ; tree.set ( 60 , 92 , 0 ) ;
int minimum = tree.minValue ( 130 , 1400 ) ;
System .
out .
println ( "Min в BitSegmentedArray отрабатывает за " + ( end
- start
) + " нс." ) ; tree.print ( ) ;
}
}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmlvLio7CgovKioKICogQ3JlYXRlZCBieSBncmVlbiBvbiAyOC4xMS4xNS4KICovCgppbXBvcnQgamF2YS5zZWN1cml0eS5LZXk7CgovKioKICogQ3JlYXRlZCBieSBncmVlbiBvbiAyNi4xMS4xNS4KICovCgppbnRlcmZhY2UgU2VnbWVudGVkQXJyYXk8VD4gewogICAgLyoqCiAgICAgKiA8cD5HZXQgdmFsdWUgYnkgZWxlbWVudCBpbmRleDwvcD4KICAgICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiBlbGVtZW50LgogICAgICogQHJldHVybiAgVmFsdWUgb2YgZWxlbWVudCB3aXRoIHNwZWNpZmllZCBpbmRleC4KICAgICAqLwogICAgVCBnZXQoaW50IGluZGV4KTsKCiAgICAvKioKICAgICAqIDxwPlNldCB0aGUgc2FtZSB2YWx1ZSBmb3IgYWxsIGVsZW1lbnRzIGluIHRoZSBzcGVjaWZpZWQgaW5kZXggcmFuZ2U8L3A+CiAgICAgKiBAcGFyYW0gc3RhcnQgdGhlIGJlZ2lubmluZyBpbmRleCwgaW5jbHVzaXZlLgogICAgICogQHBhcmFtIGVuZCB0aGUgZW5kaW5nIGluZGV4LCBleGNsdXNpdmUuCiAgICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgZm9yLgogICAgICovCiAgICB2b2lkIHNldChpbnQgc3RhcnQsIGludCBlbmQsIFQgdmFsdWUpOwoKICAgIC8qKgogICAgICogPHA+UmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgYXJyYXkgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIHNwZWNpZmllZCB2YWx1ZSwKICAgICAqIHN0YXJ0aW5nIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguIElmIG5vIHN1Y2ggdmFsdWUgb2YgayBleGlzdHMsIHRoZW4gLTEgaXMgcmV0dXJuZWQuPC9wPgogICAgICogQHBhcmFtIHZhbHVlIHRoZSBULWJhc2VkIHZhbHVlIGZvciB3aGljaCB0byBzZWFyY2guCiAgICAgKiBAcGFyYW0gZnJvbUluZGV4IHRoZSBpbmRleCBmcm9tIHdoaWNoIHRvIHN0YXJ0IHRoZSBzZWFyY2guCiAgICAgKiBAcmV0dXJuIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBhcnJheSBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZWxlbWVudCB3aXRoIHNwZWNpZmllZCB2YWx1ZSwKICAgICAqIHN0YXJ0aW5nIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgKi8KICAgICBpbnQgaW5kZXhPZihUIHZhbHVlLCBpbnQgZnJvbUluZGV4KTsKCiAgICAvKioKICAgICAqIDxwPkZpbmQgbWluaW11bSB2YWx1ZSBpbiB0aGUgc3BlY2lmaWVkIGluZGV4ZXMgcmFuZ2U8L3A+CiAgICAgKiBAcGFyYW0gc3RhcnQgdGhlIGJlZ2lubmluZyBpbmRleCwgaW5jbHVzaXZlLgogICAgICogQHBhcmFtIGVuZCB0aGUgZW5kaW5nIGluZGV4LCBleGNsdXNpdmUuCiAgICAgKiBAcmV0dXJuIE1pbmltdW0gdmFsdWUuCiAgICAgKi8KICAgICBUIG1pblZhbHVlKGludCBzdGFydCwgaW50IGVuZCk7Cn0KCgpjbGFzcyBDVCA8VmFsdWUgZXh0ZW5kcyBDb21wYXJhYmxlPFZhbHVlPj4gIGltcGxlbWVudHMgU2VnbWVudGVkQXJyYXk8VmFsdWU+ewoKICAgIHByaXZhdGUgY2xhc3MgTm9kZSB7CiAgICAgICAgVmFsdWUgdmFsdWU7CiAgICAgICAgaW50IGwsIHI7CiAgICAgICAgTm9kZSBsZWZ0LCByaWdodCwgZmF0aGVyOwogICAgICAgIHB1YmxpYyBOb2RlIChWYWx1ZSB2YWx1ZSwgTm9kZSBmYXRoZXIsIGludCBsLCBpbnQgcikgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgIHRoaXMubGVmdCA9IHRoaXMucmlnaHQgPSBudWxsOwogICAgICAgICAgICB0aGlzLmZhdGhlciA9IGZhdGhlcjsKICAgICAgICAgICAgdGhpcy5sID0gbDsgdGhpcy5yID0gcjsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBOb2RlIHJvb3Q7CgogICAgcHJpdmF0ZSBOb2RlIGFkZCAoTm9kZSBub2RlLFZhbHVlIHZhbHVlLCBOb2RlIGZhdGhlciwgaW50IGwsIGludCByKXsKICAgICAgICBpZiAobm9kZSA9PSBudWxsKXsKICAgICAgICAgICAgTm9kZSBuZXdub2RlID0gbmV3IE5vZGUodmFsdWUsZmF0aGVyLCBsICwgcik7CiAgICAgICAgICAgIHJldHVybiBuZXdub2RlOwogICAgICAgIH0KICAgICAgICAvL2ludCBjb21wYXJlUmVzdWx0bCA9IGwuY29tcGFyZVRvKG5vZGUubCk7CiAgICAgICAgLy9pbnQgY29tcGFyZVJlc3VsdHIgPSByLmNvbXBhcmVUbyhub2RlLnIpOwogICAgICAgIGlmKGwgPiBub2RlLnIpewogICAgICAgICAgICBub2RlLnJpZ2h0ID0gYWRkKG5vZGUucmlnaHQsIHZhbHVlLCBub2RlLCBsLCByKTsKICAgICAgICB9ZWxzZSBpZihyIDwgbm9kZS5sKXsKICAgICAgICAgICAgbm9kZS5sZWZ0ID0gYWRkKG5vZGUubGVmdCwgdmFsdWUsIG5vZGUsIGwsIHIpOwogICAgICAgIH1lbHNlIGlmKGwgPj0gbm9kZS5sICYmIHIgPD0gbm9kZS5yKXsKICAgICAgICAgICAgaWYobCA9PSBub2RlLmwgJiYgciA9PSBub2RlLnIpewogICAgICAgICAgICAgICAgbm9kZS52YWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7CiAgICAgICAgICAgIH1lbHNlIGlmKGwgPT0gbm9kZS5sKXsKICAgICAgICAgICAgICAgIG5vZGUucmlnaHQgPSBhZGQobm9kZS5yaWdodCwgbm9kZS52YWx1ZSwgbm9kZSwgcisxLCBub2RlLnIpOwogICAgICAgICAgICAgICAgbm9kZS52YWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgbm9kZS5yID0gcjsKICAgICAgICAgICAgfWVsc2UgaWYociA9PSBub2RlLnIpewogICAgICAgICAgICAgICAgbm9kZS5sZWZ0ID0gYWRkKG5vZGUubGVmdCwgbm9kZS52YWx1ZSwgbm9kZSwgbm9kZS5sLCBsLTEpOwogICAgICAgICAgICAgICAgbm9kZS52YWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgbm9kZS5sID0gbDsKICAgICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgICAgICBOb2RlIG5ld25vZGUgPSBuZXcgTm9kZSh2YWx1ZSxmYXRoZXIsIGwgLCByKTsKICAgICAgICAgICAgICAgIG5ld25vZGUubGVmdCA9IG5vZGUubGVmdDsKICAgICAgICAgICAgICAgIG5ld25vZGUucmlnaHQgPSBub2RlLnJpZ2h0OwogICAgICAgICAgICAgICAgbmV3bm9kZS5sZWZ0ID0gYWRkKG5ld25vZGUubGVmdCwgbm9kZS52YWx1ZSwgbmV3bm9kZSwgbm9kZS5sLCBsLTEpOwogICAgICAgICAgICAgICAgbmV3bm9kZS5yaWdodCA9IGFkZChuZXdub2RlLnJpZ2h0LCBub2RlLnZhbHVlLCBuZXdub2RlLCByKzEsIG5vZGUucik7CiAgICAgICAgICAgICAgICBub2RlID0gbmV3bm9kZTsKICAgICAgICAgICAgfQogICAgICAgIH1lbHNlIGlmKGwgPCBub2RlLmwgJiYgciA+IG5vZGUucil7CiAgICAgICAgICAgIG5vZGUudmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgbm9kZS5sID0gbDsKICAgICAgICAgICAgbm9kZS5yID0gcjsKICAgICAgICAgICAgbm9kZS5sZWZ0ID0gZGVsZXRlKG5vZGUubGVmdCwgbCwgZmFsc2UpOwogICAgICAgICAgICBub2RlLnJpZ2h0ID0gZGVsZXRlKG5vZGUucmlnaHQsIHIsIHRydWUpOwogICAgICAgIH1lbHNlIGlmKGwgPCBub2RlLmwpewogICAgICAgICAgICBpZihyID09IG5vZGUucil7CiAgICAgICAgICAgICAgICBub2RlLnZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgICBub2RlLmwgPSBsOwogICAgICAgICAgICAgICAgbm9kZS5sZWZ0ID0gZGVsZXRlKG5vZGUubGVmdCwgbCwgZmFsc2UpOwogICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgIG5vZGUgPSBhZGQobm9kZSwgbm9kZS52YWx1ZSwgZmF0aGVyLCByKzEsIG5vZGUucik7CiAgICAgICAgICAgICAgICBub2RlID0gYWRkKG5vZGUsIHZhbHVlLCBmYXRoZXIsIGwsIHIpOwogICAgICAgICAgICB9CiAgICAgICAgfWVsc2UgaWYgKHIgPiBub2RlLnIpIHsKICAgICAgICAgICAgaWYgKGwgPT0gbm9kZS5sKSB7CiAgICAgICAgICAgICAgICBub2RlLnZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgICBub2RlLnIgPSByOwogICAgICAgICAgICAgICAgbm9kZS5yaWdodCA9IGRlbGV0ZShub2RlLnJpZ2h0LCByLCB0cnVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG5vZGUgPSBhZGQobm9kZSwgbm9kZS52YWx1ZSwgZmF0aGVyLCBub2RlLmwsIGwgLSAxKTsKICAgICAgICAgICAgICAgIG5vZGUgPSBhZGQobm9kZSwgdmFsdWUsIGZhdGhlciwgbCwgcik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5vZGU7CiAgICB9CgogICAgcHVibGljIHZvaWQgc2V0KGludCBsLCBpbnQgciwgVmFsdWUgdmFsdWUpIHsKICAgICAgICByb290ID0gYWRkKHJvb3QsIHZhbHVlLCBudWxsLCBsLCByKTsKICAgIH0KICAgIHByaXZhdGUgTm9kZSBkZWxldGUoTm9kZSBub2RlLCBpbnQgZCwgQm9vbGVhbiBzaWRlKXsKICAgICAgICBpZihub2RlID09IG51bGwpIHJldHVybiBudWxsOwogICAgICAgIGlmKGQgPCBub2RlLnIgJiYgZCA+IG5vZGUubCl7CiAgICAgICAgICAgIG5vZGUgPSBhZGQobm9kZSwgbm9kZS52YWx1ZSwgbm9kZS5mYXRoZXIsIG5vZGUubCwgZCAtIDEpOwogICAgICAgICAgICBub2RlID0gZGVsZXRlKG5vZGUsIGQsIHNpZGUpOwogICAgICAgIH1lbHNlIGlmKGQgPCBub2RlLmwpewogICAgICAgICAgICBpZihzaWRlKQogICAgICAgICAgICAgICAgbm9kZS5sZWZ0ID0gZGVsZXRlKG5vZGUubGVmdCwgZCwgc2lkZSk7CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUubGVmdDsKICAgICAgICAgICAgICAgIG5vZGUgPSBkZWxldGUobm9kZSwgZCwgc2lkZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9ZWxzZSBpZihkID4gbm9kZS5yKXsKICAgICAgICAgICAgaWYoc2lkZSkgewogICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUucmlnaHQ7CiAgICAgICAgICAgICAgICBub2RlID0gZGVsZXRlKG5vZGUsIGQsIHNpZGUpOwogICAgICAgICAgICB9ZWxzZQogICAgICAgICAgICAgICAgbm9kZS5yaWdodCA9IGRlbGV0ZShub2RlLnJpZ2h0LCBkLCBzaWRlKTsKICAgICAgICB9ZWxzZSBpZihkID09IG5vZGUucil7CiAgICAgICAgICAgIGlmKHNpZGUpIHtub2RlID0gbm9kZS5yaWdodDt9IGVsc2Uge25vZGUucmlnaHQgPSBudWxsO25vZGUuciA9IGQgLSAxO30KICAgICAgICB9ZWxzZSBpZihkID09IG5vZGUubCl7CiAgICAgICAgICAgIGlmKHNpZGUpIHtub2RlLmxlZnQgPSBudWxsO25vZGUubCA9IGQgKyAxO30gZWxzZSB7bm9kZSA9IG5vZGUubGVmdDt9CiAgICAgICAgfQogICAgICAgIHJldHVybiBub2RlOwogICAgfQoKICAgIHByaXZhdGUgVmFsdWUgZ2V0KE5vZGUgbm9kZSwgaW50IGluZGV4KXsKICAgICAgICBpZihub2RlID09IG51bGwpIHJldHVybiBudWxsOwogICAgICAgIGlmKGluZGV4ID4gbm9kZS5yKQogICAgICAgICAgICByZXR1cm4gZ2V0KG5vZGUucmlnaHQsIGluZGV4KTsKICAgICAgICBlbHNlIGlmIChpbmRleCA8IG5vZGUubCkKICAgICAgICAgICAgcmV0dXJuIGdldChub2RlLmxlZnQsIGluZGV4KTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBub2RlLnZhbHVlOwogICAgfQoKICAgIHB1YmxpYyBWYWx1ZSBnZXQoaW50IGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGdldChyb290LCBpbmRleCk7CiAgICB9CgogICAgcHJpdmF0ZSBWYWx1ZSBtaW5pbXVtKFZhbHVlIHgsIFZhbHVlIHkpewogICAgICAgIGlmKHggPT0gbnVsbCAmJiB5ID09IG51bGwpIHJldHVybiBudWxsOwogICAgICAgIGVsc2UgaWYoeCA9PSBudWxsKSByZXR1cm4geTsKICAgICAgICBlbHNlIGlmKHkgPT0gbnVsbCkgcmV0dXJuIHg7CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGlmICh4LmNvbXBhcmVUbyh5KSA9PSAxKSByZXR1cm4geTsKICAgICAgICAgICAgZWxzZSByZXR1cm4geDsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBWYWx1ZSBtaW4oTm9kZSBub2RlLCBpbnQgc3RhcnQsIGludCBlbmQpewogICAgICAgIGlmKG5vZGUgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICAgICAgaWYoZW5kIDwgbm9kZS5sKXsKICAgICAgICAgICAgcmV0dXJuIG1pbihub2RlLmxlZnQsIHN0YXJ0LCBlbmQpOwogICAgICAgIH1lbHNlIGlmIChzdGFydCA+IG5vZGUucil7CiAgICAgICAgICAgIHJldHVybiBtaW4obm9kZS5yaWdodCwgc3RhcnQsIGVuZCk7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAgIFZhbHVlIHYxID0gbnVsbCwgdjIgPSBudWxsOwogICAgICAgICAgICBpZihzdGFydCA8IG5vZGUubCkgdjEgPSBtaW4obm9kZS5sZWZ0LCBzdGFydCwgZW5kKTsKICAgICAgICAgICAgaWYoZW5kID4gbm9kZS5yKSB2MiA9IG1pbihub2RlLnJpZ2h0LCBzdGFydCwgZW5kKTsKICAgICAgICAgICAgcmV0dXJuIG1pbmltdW0odjIsIG1pbmltdW0obm9kZS52YWx1ZSwgdjEpKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIFZhbHVlIG1pblZhbHVlKGludCBzdGFydCwgaW50IGVuZCl7CiAgICAgICAgcmV0dXJuIG1pbihyb290LCBzdGFydCwgZW5kKTsKICAgIH0KCiAgICBwcml2YXRlIEludGVnZXIgaW5kZXhPZihOb2RlIG5vZGUsIFZhbHVlIHZhbHVlLCBpbnQgaW5kZXgpewogICAgICAgIGlmKG5vZGUgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICAgICAgaWYoaW5kZXggPD0gbm9kZS5yKSB7CiAgICAgICAgICAgIEludGVnZXIgdiA9IG51bGw7CiAgICAgICAgICAgIGlmKGluZGV4IDwgbm9kZS5sKXsKICAgICAgICAgICAgICAgIHYgPSBpbmRleE9mKG5vZGUubGVmdCwgdmFsdWUsIGluZGV4KTsKICAgICAgICAgICAgICAgIGlmICh2ICE9IG51bGwpIHJldHVybiB2OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBub2RlLnZhbHVlKSByZXR1cm4gTWF0aC5tYXgobm9kZS5sLCBpbmRleCk7CiAgICAgICAgICAgIHYgPSBpbmRleE9mKG5vZGUucmlnaHQsIHZhbHVlLCBpbmRleCk7CiAgICAgICAgICAgIGlmICh2ICE9IG51bGwpIHJldHVybiB2OwogICAgICAgIH0KICAgICAgICByZXR1cm4gaW5kZXhPZihub2RlLnJpZ2h0LCB2YWx1ZSwgaW5kZXgpOwogICAgfQoKICAgIHB1YmxpYyBpbnQgaW5kZXhPZihWYWx1ZSB2YWx1ZSwgaW50IGluZGV4KXsKICAgICAgICByZXR1cm4gaW5kZXhPZihyb290LCB2YWx1ZSwgaW5kZXgpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCBwcmludChOb2RlIG5vZGUsIGludCBsZXZlbCkgewogICAgICAgIGlmIChub2RlICE9IG51bGwpIHsKICAgICAgICAgICAgcHJpbnQobm9kZS5yaWdodCxsZXZlbCsxKTsKICAgICAgICAgICAgZm9yIChpbnQgaT0wO2k8bGV2ZWw7aSsrKSB7CiAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50KCJcdCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihub2RlLmwgKyAiLSIgKyBub2RlLnIgKyAiLT4iICsgbm9kZS52YWx1ZSk7CiAgICAgICAgICAgIHByaW50KG5vZGUubGVmdCxsZXZlbCsxKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHZvaWQgcHJpbnQoKSB7CiAgICAgICAgcHJpbnQocm9vdCwwKTsKICAgIH0KCn0KCgoKLyogTmFtZSBvZiB0aGUgY2xhc3MgaGFzIHRvIGJlICJNYWluIiBvbmx5IGlmIHRoZSBjbGFzcyBpcyBwdWJsaWMuICovCmNsYXNzIElkZW9uZQp7CglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbiAoU3RyaW5nW10gYXJncykgdGhyb3dzIGphdmEubGFuZy5FeGNlcHRpb24KCXsKICAgICAgICBDVDxJbnRlZ2VyPiB0cmVlID0gbmV3IENUPD4oKTsKICAgICAgICBsb25nIHN0YXJ0LCBlbmQ7CiAgICAgICAgc3RhcnQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICB0cmVlLnNldCg1MCwgNDU2NiwgMTQpOwogICAgICAgIC8vdHJlZS5zZXQoMTMwLCA3NDAsIDI5MDEyKTsKICAgICAgICAvL3RyZWUuc2V0KDEwMDAsIDEwODQsIC0yKTsKICAgICAgICAvL3RyZWUuc2V0KDMwMDYsIDMwNzAsIDUxKTsKICAgICAgICBlbmQgPSBTeXN0ZW0ubmFub1RpbWUoKTsvL3RyZWUuc2V0KDUwLCA0NTY2LCAxNCk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCLQn9C10YDQstGL0LkgU2V0INCyIEJpdFNlZ21lbnRlZEFycmF5INC+0YLRgNCw0LHQsNGC0YvQstCw0LXRgiDQt9CwICIgKyAoZW5kIC0gc3RhcnQpICsgIiDQvdGBLiIpOwoKICAgICAgICBzdGFydCA9IFN5c3RlbS5uYW5vVGltZSgpOwogICAgICAgIEludGVnZXIgZ2V0ID0gdHJlZS5nZXQoMTExKTsKICAgICAgICBlbmQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIkdldCDQsiBCaXRTZWdtZW50ZWRBcnJheSDQvtGC0YDQsNCx0LDRgtGL0LLQsNC10YIg0LfQsCAiICsgKGVuZCAtIHN0YXJ0KSArICIg0L3RgS4iKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oZ2V0KTsKCiAgICAgICAgc3RhcnQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICB0cmVlLnNldCg3NiwgODMwLCAxKTsKICAgICAgICBlbmQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oItCS0YLQvtGA0L7QuSBTZXQg0LIgQml0U2VnbWVudGVkQXJyYXkg0L7RgtGA0LDQsdCw0YLRi9Cy0LDQtdGCINC30LAgIiArIChlbmQgLSBzdGFydCkgKyAiINC90YEuIik7CiAgICAgICAgdHJlZS5zZXQoNjAsIDkyLCAwKTsKCiAgICAgICAgc3RhcnQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICBpbnQgbWluaW11bSA9IHRyZWUubWluVmFsdWUoMTMwLCAxNDAwKTsKICAgICAgICBlbmQgPSBTeXN0ZW0ubmFub1RpbWUoKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIk1pbiDQsiBCaXRTZWdtZW50ZWRBcnJheSDQvtGC0YDQsNCx0LDRgtGL0LLQsNC10YIg0LfQsCAiICsgKGVuZCAtIHN0YXJ0KSArICIg0L3RgS4iKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4obWluaW11bSk7CiAgICAgICAgdHJlZS5wcmludCgpOwogICAgfQp9