#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <set>
using namespace std;
struct Point { int x, y; };
bool operator==(Point const& p1, Point const& p2)
{
return p1.x == p2.x && p1.y == p2.y;
}
bool operator<(Point const& p1, Point const& p2)
{
return p1.x != p2.x ? p1.x < p2.x : p1.y < p2.y;
}
void addToSortedVector(std::vector<Point>& v, const Point &p){
auto it = std::lower_bound(v.begin(),v.end(),p);
if(it == v.end() || !(*it == p)){
v.insert(it,p);
}
}
void __attribute__ ((noinline))test1(const std::vector<Point>& in,std::vector<int>& out){
std::set<Point> points{};
for(const auto&i:in){
points.insert(i);
}
out.push_back(points.size());
}
void __attribute__ ((noinline))test2(const std::vector<Point>& in,std::vector<int>& out){
std::vector<Point> points{};
for(const auto&i:in){
addToSortedVector(points,i);
}
out.push_back(points.size());
}
int main() {
const std::vector<Point> input{{{99,0},{98,0},{97,4},{96,4},{95,0},{94,3},{93,0},{92,0},{91,2},{90,0},{89,0},{88,0},{87,4},{4,4},{0,0},{0,3},{2,2},{0,9},{0,2},{1,0},{0,0},{0,0},{4,4},{4,4},{0,0},{0,3},{0,0},{0,0},{0,2},{1,0},{0,0},{0,0},{4,4},{4,4},{0,0},{0,3},{2,2},{3,9},{03,2},{1,3},{0,3},{3,0},{2,4},{3,4},{5,0},{05,3},{0,5},{5,0},{5,2},{1,5},{5,0},{6,0},{6,4},{7,4},{7,0},{7,3},{7,2},{7,9},{7,2},{1,7}}};
std::vector<int> out;
std::chrono::nanoseconds time[2]{{},{}};
for(int i=0;i<100;i++){
const auto t1 = std::chrono::high_resolution_clock::now();
test1(input,out);
const auto t2 = std::chrono::high_resolution_clock::now();
time[0] += t2 - t1;
const auto t3 = std::chrono::high_resolution_clock::now();
test2(input,out);
const auto t4 = std::chrono::high_resolution_clock::now();
time[1] += t4 - t3;
}
typedef std::chrono::nanoseconds output_time;
const char* const out_unit = " ns";
std::cout << "1: " << std::chrono::duration_cast<output_time>(time[0]).count() << out_unit << "\n";
std::cout << "2: " << std::chrono::duration_cast<output_time>(time[1]).count() << out_unit << "\n";
cout << out.size(); //just to stop the optimizer from stomping on us
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y2hyb25vPgojaW5jbHVkZSA8c2V0Pgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKc3RydWN0IFBvaW50IHsgaW50IHgsIHk7IH07CmJvb2wgb3BlcmF0b3I9PShQb2ludCBjb25zdCYgcDEsIFBvaW50IGNvbnN0JiBwMikKewoJcmV0dXJuIHAxLnggPT0gcDIueCAmJiBwMS55ID09IHAyLnk7Cn0KCmJvb2wgb3BlcmF0b3I8KFBvaW50IGNvbnN0JiBwMSwgUG9pbnQgY29uc3QmIHAyKQp7CglyZXR1cm4gcDEueCAhPSBwMi54ID8gcDEueCA8IHAyLnggOiBwMS55IDwgcDIueTsKfQoKdm9pZCBhZGRUb1NvcnRlZFZlY3RvcihzdGQ6OnZlY3RvcjxQb2ludD4mIHYsIGNvbnN0IFBvaW50ICZwKXsKCWF1dG8gaXQgPSBzdGQ6Omxvd2VyX2JvdW5kKHYuYmVnaW4oKSx2LmVuZCgpLHApOwoJaWYoaXQgPT0gdi5lbmQoKSB8fCAhKCppdCA9PSBwKSl7CgkJdi5pbnNlcnQoaXQscCk7Cgl9Cn0KCgp2b2lkIF9fYXR0cmlidXRlX18gKChub2lubGluZSkpdGVzdDEoY29uc3Qgc3RkOjp2ZWN0b3I8UG9pbnQ+JiBpbixzdGQ6OnZlY3RvcjxpbnQ+JiBvdXQpewoJc3RkOjpzZXQ8UG9pbnQ+IHBvaW50c3t9OwoJZm9yKGNvbnN0IGF1dG8maTppbil7CgkJcG9pbnRzLmluc2VydChpKTsKCX0KCW91dC5wdXNoX2JhY2socG9pbnRzLnNpemUoKSk7Cn0Kdm9pZCBfX2F0dHJpYnV0ZV9fICgobm9pbmxpbmUpKXRlc3QyKGNvbnN0IHN0ZDo6dmVjdG9yPFBvaW50PiYgaW4sc3RkOjp2ZWN0b3I8aW50PiYgb3V0KXsKCXN0ZDo6dmVjdG9yPFBvaW50PiBwb2ludHN7fTsKCWZvcihjb25zdCBhdXRvJmk6aW4pewoJCWFkZFRvU29ydGVkVmVjdG9yKHBvaW50cyxpKTsKCX0KCW91dC5wdXNoX2JhY2socG9pbnRzLnNpemUoKSk7Cn0KCgoKaW50IG1haW4oKSB7Cgljb25zdCBzdGQ6OnZlY3RvcjxQb2ludD4gaW5wdXR7e3s5OSwwfSx7OTgsMH0sezk3LDR9LHs5Niw0fSx7OTUsMH0sezk0LDN9LHs5MywwfSx7OTIsMH0sezkxLDJ9LHs5MCwwfSx7ODksMH0sezg4LDB9LHs4Nyw0fSx7NCw0fSx7MCwwfSx7MCwzfSx7MiwyfSx7MCw5fSx7MCwyfSx7MSwwfSx7MCwwfSx7MCwwfSx7NCw0fSx7NCw0fSx7MCwwfSx7MCwzfSx7MCwwfSx7MCwwfSx7MCwyfSx7MSwwfSx7MCwwfSx7MCwwfSx7NCw0fSx7NCw0fSx7MCwwfSx7MCwzfSx7MiwyfSx7Myw5fSx7MDMsMn0sezEsM30sezAsM30sezMsMH0sezIsNH0sezMsNH0sezUsMH0sezA1LDN9LHswLDV9LHs1LDB9LHs1LDJ9LHsxLDV9LHs1LDB9LHs2LDB9LHs2LDR9LHs3LDR9LHs3LDB9LHs3LDN9LHs3LDJ9LHs3LDl9LHs3LDJ9LHsxLDd9fX07CglzdGQ6OnZlY3RvcjxpbnQ+IG91dDsKIAoJc3RkOjpjaHJvbm86Om5hbm9zZWNvbmRzIHRpbWVbMl17e30se319OwogCglmb3IoaW50IGk9MDtpPDEwMDtpKyspewoJCWNvbnN0IGF1dG8gdDEgPSBzdGQ6OmNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCQl0ZXN0MShpbnB1dCxvdXQpOwoJCWNvbnN0IGF1dG8gdDIgPSBzdGQ6OmNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCQl0aW1lWzBdICs9IHQyIC0gdDE7CgkJY29uc3QgYXV0byB0MyA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoJCXRlc3QyKGlucHV0LG91dCk7CgkJY29uc3QgYXV0byB0NCA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoJCXRpbWVbMV0gKz0gdDQgLSB0MzsKCX0KIAoJdHlwZWRlZiBzdGQ6OmNocm9ubzo6bmFub3NlY29uZHMgb3V0cHV0X3RpbWU7Cgljb25zdCBjaGFyKiBjb25zdCBvdXRfdW5pdCA9ICIgbnMiOwogCglzdGQ6OmNvdXQgPDwgIjE6ICIgPDwgc3RkOjpjaHJvbm86OmR1cmF0aW9uX2Nhc3Q8b3V0cHV0X3RpbWU+KHRpbWVbMF0pLmNvdW50KCkgPDwgb3V0X3VuaXQgPDwgIlxuIjsKCXN0ZDo6Y291dCA8PCAiMjogIiA8PCBzdGQ6OmNocm9ubzo6ZHVyYXRpb25fY2FzdDxvdXRwdXRfdGltZT4odGltZVsxXSkuY291bnQoKSA8PCBvdXRfdW5pdCA8PCAiXG4iOwoJY291dCA8PCBvdXQuc2l6ZSgpOyAvL2p1c3QgdG8gc3RvcCB0aGUgb3B0aW1pemVyIGZyb20gc3RvbXBpbmcgb24gdXMKCXJldHVybiAwOwp9