#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <tuple>
#include <iomanip>
using namespace std;
/** A point in the stream.
*
* point where (at a specific time) the value changes.
* */
template < typename T>
struct Point {
using value_type = T;
float time ;
T value;
} ;
/** Alias to break through a single iterator layer. */
template < typename Iterator>
using Behind1Iterator =
typename iterator_traits< Iterator> :: value_type ;
/** Alias to break through 2 layers of iterators. */
template < typename Iterator>
using Behind2Iterators =
Behind1Iterator< typename Behind1Iterator< Iterator> :: iterator > ;
/** Merge streams (sorted ranges of points) into a single, final stream, with
* the values superimposed. */
template <
typename Iterator,
typename Out
>
void merge_point_lists(
Iterator from, Iterator to,
Out out) {
using namespace std;
// Iterator type of the containers which are the values
// of the given range [from,to)
using StreamIterator = typename Behind1Iterator< Iterator> :: iterator ;
// value_type of the Points
using Value = typename Behind2Iterators< Iterator> :: value_type ;
// Information about each of the streams:
// 1. the current effect on the result stream
// 2. iterator to the next time point in the stream
// 3. end of the stream
vector< tuple< Value, StreamIterator, StreamIterator>> streams;
transform( from, to, inserter( streams, begin( streams) ) ,
[ ] ( auto & stream) {
return make_tuple( static_cast < Value> ( 0 ) , begin( stream) , end( stream) ) ;
} ) ;
// Comparator to generate a min heap (!), where the top element is
// the information for the stream, whose next value is the earliest.
auto heap_compare = [ ] ( auto const & lhs, auto const & rhs) {
bool less = ( * get< 1 > ( lhs) ) .time < ( * get< 1 > ( rhs) ) .time ;
return ( not less) ;
} ;
// The current value of the result stream.
Value current = 0 ;
while ( streams.size ( ) > 0 ) {
// Reorder the stream information to get the one with the earliest next
// value into top ...
make_heap( begin( streams) , end( streams) , heap_compare) ;
// .. and select it.
auto & earliest = streams[ 0 ] ;
// New value is the current one, minus the previous effect of the selected
// stream plus the new value from the selected stream
current = current - get< 0 > ( earliest) + ( * get< 1 > ( earliest) ) .value ;
// Store the new time point with the new value and the time of the used
// time point from the selected stream
* out++ = Point< Value> { ( * get< 1 > ( earliest) ) .time , current} ;
// Update the effect of the selected stream
get< 0 > ( earliest) = ( * get< 1 > ( earliest) ) .value ;
// Advance selected stream to its next time point
++ ( get< 1 > ( earliest) ) ;
// Remove stream if empty
if ( get< 1 > ( earliest) == get< 2 > ( earliest) ) {
swap( streams[ 0 ] , streams[ streams.size ( ) - 1u] ) ;
streams.pop_back ( ) ;
}
}
}
int main( int , char ** ) {
vector< Point< int >> input[ ] = {
{ { 0.5 ,1 } , { 2 ,2 } , { 3.2 ,3 } , { 4 ,0 } } ,
{ { 1 ,10 } , { 2 ,20 } , { 3 ,30 } , { 4.5 ,0 } } ,
{ { 3.14 ,100 } , { 6.28 ,200 } , { 10 ,0 } } ,
{ { 1.5 ,1000 } ,{ 2.5 ,0 } } } ;
vector< Point< int >> merged;
merge_point_lists( begin( input) , end( input) , inserter( merged, begin( merged) ) ) ;
// returns points with the same time, but with different values. remove these
// duplicates, by first making them REALLY equal, i.e. setting their values
// to the last value ...
for ( auto write = begin( merged) , read = begin( merged) , stop = end( merged) ;
write ! = stop; ) {
for ( ++ read; ( read ! = stop) and ( read- > time == write- > time ) ; ++ read) {
write- > value = read- > value;
}
for ( auto const cached = ( write++ ) - > value; write ! = read; ++ write) {
write- > value = cached;
}
}
// ... and then removing them.
merged.erase (
unique( begin( merged) , end( merged) ,
[ ] ( auto const & lhs, auto const & rhs) {
return ( lhs.time == rhs.time ) ; } ) ,
end( merged) ) ;
// print the result
for ( auto const & point : merged) {
cout << "@" << setw( 4 ) << point.time << " change to " << setw( 5 ) << point.value << endl;
}
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPGlvbWFuaXA+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovKiogQSBwb2ludCBpbiB0aGUgc3RyZWFtLgogKiAKICogcG9pbnQgd2hlcmUgKGF0IGEgc3BlY2lmaWMgdGltZSkgdGhlIHZhbHVlIGNoYW5nZXMuCiAqICovCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBQb2ludCB7CiAgdXNpbmcgdmFsdWVfdHlwZSA9IFQ7CiAgZmxvYXQgdGltZTsKICBUIHZhbHVlOwp9OwoKLyoqIEFsaWFzIHRvIGJyZWFrIHRocm91Z2ggYSBzaW5nbGUgaXRlcmF0b3IgbGF5ZXIuICovCnRlbXBsYXRlPHR5cGVuYW1lIEl0ZXJhdG9yPgp1c2luZyBCZWhpbmQxSXRlcmF0b3IgPQogIHR5cGVuYW1lIGl0ZXJhdG9yX3RyYWl0czxJdGVyYXRvcj46OnZhbHVlX3R5cGU7CgovKiogQWxpYXMgdG8gYnJlYWsgdGhyb3VnaCAyIGxheWVycyBvZiBpdGVyYXRvcnMuICovCnRlbXBsYXRlPHR5cGVuYW1lIEl0ZXJhdG9yPgp1c2luZyBCZWhpbmQySXRlcmF0b3JzID0KICBCZWhpbmQxSXRlcmF0b3I8dHlwZW5hbWUgQmVoaW5kMUl0ZXJhdG9yPEl0ZXJhdG9yPjo6aXRlcmF0b3I+OwoKLyoqIE1lcmdlIHN0cmVhbXMgKHNvcnRlZCByYW5nZXMgb2YgcG9pbnRzKSBpbnRvIGEgc2luZ2xlLCBmaW5hbCBzdHJlYW0sIHdpdGgKICogdGhlIHZhbHVlcyBzdXBlcmltcG9zZWQuICovCnRlbXBsYXRlPAogdHlwZW5hbWUgSXRlcmF0b3IsCiB0eXBlbmFtZSBPdXQKID4Kdm9pZCBtZXJnZV9wb2ludF9saXN0cygKICAgICAgSXRlcmF0b3IgZnJvbSwgSXRlcmF0b3IgdG8sCiAgICAgIE91dCBvdXQpIHsKICB1c2luZyBuYW1lc3BhY2Ugc3RkOwogIC8vIEl0ZXJhdG9yIHR5cGUgb2YgdGhlIGNvbnRhaW5lcnMgd2hpY2ggYXJlIHRoZSB2YWx1ZXMKICAvLyBvZiB0aGUgZ2l2ZW4gcmFuZ2UgW2Zyb20sdG8pCiAgdXNpbmcgU3RyZWFtSXRlcmF0b3IgPSB0eXBlbmFtZSBCZWhpbmQxSXRlcmF0b3I8SXRlcmF0b3I+OjppdGVyYXRvcjsKICAvLyB2YWx1ZV90eXBlIG9mIHRoZSBQb2ludHMKICB1c2luZyBWYWx1ZSA9IHR5cGVuYW1lIEJlaGluZDJJdGVyYXRvcnM8SXRlcmF0b3I+Ojp2YWx1ZV90eXBlOwogIC8vIEluZm9ybWF0aW9uIGFib3V0IGVhY2ggb2YgdGhlIHN0cmVhbXM6CiAgLy8gMS4gdGhlIGN1cnJlbnQgZWZmZWN0IG9uIHRoZSByZXN1bHQgc3RyZWFtCiAgLy8gMi4gaXRlcmF0b3IgdG8gdGhlIG5leHQgdGltZSBwb2ludCBpbiB0aGUgc3RyZWFtCiAgLy8gMy4gZW5kIG9mIHRoZSBzdHJlYW0KICB2ZWN0b3I8dHVwbGU8VmFsdWUsIFN0cmVhbUl0ZXJhdG9yLCBTdHJlYW1JdGVyYXRvcj4+IHN0cmVhbXM7CiAgdHJhbnNmb3JtKGZyb20sIHRvLCBpbnNlcnRlcihzdHJlYW1zLCBiZWdpbihzdHJlYW1zKSksCiAgICAgIFtdIChhdXRvICYgc3RyZWFtKSB7CiAgICAgICAgcmV0dXJuIG1ha2VfdHVwbGUoc3RhdGljX2Nhc3Q8VmFsdWU+KDApLCBiZWdpbihzdHJlYW0pLCBlbmQoc3RyZWFtKSk7CiAgICAgIH0pOwogIC8vIENvbXBhcmF0b3IgdG8gZ2VuZXJhdGUgYSBtaW4gaGVhcCAoISksIHdoZXJlIHRoZSB0b3AgZWxlbWVudCBpcwogIC8vIHRoZSBpbmZvcm1hdGlvbiBmb3IgdGhlIHN0cmVhbSwgd2hvc2UgbmV4dCB2YWx1ZSBpcyB0aGUgZWFybGllc3QuCiBhdXRvIGhlYXBfY29tcGFyZSA9IFtdIChhdXRvIGNvbnN0ICYgbGhzLCBhdXRvIGNvbnN0ICYgcmhzKSB7CiAgICAgICAgIGJvb2wgbGVzcyA9ICgqZ2V0PDE+KGxocykpLnRpbWUgPCAoKmdldDwxPihyaHMpKS50aW1lOwogICAgICAgICByZXR1cm4gKG5vdCBsZXNzKTsKICAgICAgIH07CiAgLy8gVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHJlc3VsdCBzdHJlYW0uCiAgVmFsdWUgY3VycmVudCA9IDA7CiAgd2hpbGUgKHN0cmVhbXMuc2l6ZSgpID4gMCkgewogIAkvLyBSZW9yZGVyIHRoZSBzdHJlYW0gaW5mb3JtYXRpb24gdG8gZ2V0IHRoZSBvbmUgd2l0aCB0aGUgZWFybGllc3QgbmV4dAogIAkvLyB2YWx1ZSBpbnRvIHRvcCAuLi4KICAgIG1ha2VfaGVhcChiZWdpbihzdHJlYW1zKSwgZW5kKHN0cmVhbXMpLCBoZWFwX2NvbXBhcmUpOwogICAgLy8gLi4gYW5kIHNlbGVjdCBpdC4KICAgIGF1dG8gJiBlYXJsaWVzdCA9IHN0cmVhbXNbMF07CiAgICAvLyBOZXcgdmFsdWUgaXMgdGhlIGN1cnJlbnQgb25lLCBtaW51cyB0aGUgcHJldmlvdXMgZWZmZWN0IG9mIHRoZSBzZWxlY3RlZAogICAgLy8gc3RyZWFtIHBsdXMgdGhlIG5ldyB2YWx1ZSBmcm9tIHRoZSBzZWxlY3RlZCBzdHJlYW0KICAgIGN1cnJlbnQgPSBjdXJyZW50IC0gZ2V0PDA+KGVhcmxpZXN0KSArICgqZ2V0PDE+KGVhcmxpZXN0KSkudmFsdWU7CiAgICAvLyBTdG9yZSB0aGUgbmV3IHRpbWUgcG9pbnQgd2l0aCB0aGUgbmV3IHZhbHVlIGFuZCB0aGUgdGltZSBvZiB0aGUgdXNlZAogICAgLy8gdGltZSBwb2ludCBmcm9tIHRoZSBzZWxlY3RlZCBzdHJlYW0KICAgICpvdXQrKyA9IFBvaW50PFZhbHVlPnsoKmdldDwxPihlYXJsaWVzdCkpLnRpbWUsIGN1cnJlbnR9OwogICAgLy8gVXBkYXRlIHRoZSBlZmZlY3Qgb2YgdGhlIHNlbGVjdGVkIHN0cmVhbQogICAgZ2V0PDA+KGVhcmxpZXN0KSA9ICgqZ2V0PDE+KGVhcmxpZXN0KSkudmFsdWU7CiAgICAvLyBBZHZhbmNlIHNlbGVjdGVkIHN0cmVhbSB0byBpdHMgbmV4dCB0aW1lIHBvaW50CiAgICArKyhnZXQ8MT4oZWFybGllc3QpKTsKICAgIC8vIFJlbW92ZSBzdHJlYW0gaWYgZW1wdHkKICAgIGlmIChnZXQ8MT4oZWFybGllc3QpID09IGdldDwyPihlYXJsaWVzdCkpIHsKICAgICAgc3dhcChzdHJlYW1zWzBdLCBzdHJlYW1zW3N0cmVhbXMuc2l6ZSgpIC0gMXVdKTsKICAgICAgc3RyZWFtcy5wb3BfYmFjaygpOwogICAgfQogIH0KfQoKCgppbnQgbWFpbihpbnQsIGNoYXIgKiopIHsKICB2ZWN0b3I8UG9pbnQ8aW50Pj4gaW5wdXRbXSA9IHsKICAgICAge3swLjUsMX0sIHsyLDJ9LCB7My4yLDN9LCB7NCwwfX0sCiAgICAgIHt7MSwxMH0sIHsyLDIwfSwgezMsMzB9LCB7NC41LDB9fSwKICAgICAge3szLjE0LDEwMH0sIHs2LjI4LDIwMH0sIHsxMCwwfX0sCiAgICAgIHt7MS41LDEwMDB9LHsyLjUsMH19fTsKICB2ZWN0b3I8UG9pbnQ8aW50Pj4gbWVyZ2VkOwogIG1lcmdlX3BvaW50X2xpc3RzKGJlZ2luKGlucHV0KSwgZW5kKGlucHV0KSwgaW5zZXJ0ZXIobWVyZ2VkLCBiZWdpbihtZXJnZWQpKSk7CiAgLy8gcmV0dXJucyBwb2ludHMgd2l0aCB0aGUgc2FtZSB0aW1lLCBidXQgd2l0aCBkaWZmZXJlbnQgdmFsdWVzLiByZW1vdmUgdGhlc2UKICAvLyBkdXBsaWNhdGVzLCBieSBmaXJzdCBtYWtpbmcgdGhlbSBSRUFMTFkgZXF1YWwsIGkuZS4gc2V0dGluZyB0aGVpciB2YWx1ZXMKICAvLyB0byB0aGUgbGFzdCB2YWx1ZSAuLi4KICBmb3IgKGF1dG8gd3JpdGUgPSBiZWdpbihtZXJnZWQpLCByZWFkID0gYmVnaW4obWVyZ2VkKSwgc3RvcCA9IGVuZChtZXJnZWQpOwogICAgICB3cml0ZSAhPSBzdG9wOykgewogICAgZm9yICgrK3JlYWQ7IChyZWFkICE9IHN0b3ApIGFuZCAocmVhZC0+dGltZSA9PSB3cml0ZS0+dGltZSk7ICsrcmVhZCkgewogICAgICB3cml0ZS0+dmFsdWUgPSByZWFkLT52YWx1ZTsKICAgIH0KICAgIGZvciAoYXV0byBjb25zdCBjYWNoZWQgPSAod3JpdGUrKyktPnZhbHVlOyB3cml0ZSAhPSByZWFkOyArK3dyaXRlKSB7CiAgICAgIHdyaXRlLT52YWx1ZSA9IGNhY2hlZDsKICAgIH0KICB9CiAgLy8gLi4uIGFuZCB0aGVuIHJlbW92aW5nIHRoZW0uCiAgbWVyZ2VkLmVyYXNlKAogICAgICB1bmlxdWUoYmVnaW4obWVyZ2VkKSwgZW5kKG1lcmdlZCksCiAgICAgICAgICBbXShhdXRvIGNvbnN0ICYgbGhzLCBhdXRvIGNvbnN0ICYgcmhzKSB7CiAgICAgICAgICAgIHJldHVybiAobGhzLnRpbWUgPT0gcmhzLnRpbWUpO30pLAogICAgICBlbmQobWVyZ2VkKSk7CiAgLy8gcHJpbnQgdGhlIHJlc3VsdAogIGZvciAoYXV0byBjb25zdCAmIHBvaW50IDogbWVyZ2VkKSB7CiAgICBjb3V0IDw8ICJAIiA8PCBzZXR3KDQpIDw8IHBvaW50LnRpbWUgPDwgIiBjaGFuZ2UgdG8gIiA8PCBzZXR3KDUpIDw8IHBvaW50LnZhbHVlIDw8IGVuZGw7CiAgfQogIHJldHVybiAwOwp9Cg==