引言
最近在看算法题打算备战七月份的马蹄和明年的蓝桥(今年由于囊肿羞涩没有参加——有点后悔,学校的奖学金还是很多的),写来写去发现还是只能做些简单的题,重复的循环和判断让我觉得涉足更难的贪心,但一上来就遇到了一名猛将[[P7990 USACO21DEC] Closest Cow Wins S - 洛谷]。我觉得是时候开启operator了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include<bits/stdc++.h> using namespace std; int main() { int num, actor1, actor2; cin >> num >> actor1 >> actor2; vector<pair<long long,long long>> grass(num); vector<long long> Actor1(actor1); for(int i = 0; i < num; i++) cin >> grass[i].first >> grass[i].second; for(int i = 0; i < actor1; i++) cin >> Actor1[i]; sort(grass.begin(),grass.end()); sort(Actor1.begin(),Actor1.end()); vector<pair<long long,long long>> segments; if(actor1 == 0) { long long sum = 0; for(int i = 0; i < num; i++) sum += grass[i].second; segments.push_back({sum, 1}); } else { long long sum = 0; for(int i = 0; i < num; i++) { if(grass[i].first < Actor1[0]) { sum += grass[i].second; } } if(sum > 0) segments.push_back({sum, 1}); for(int j = 0; j < actor1-1; j++) { for(int i = 0; i < num; i++) { if(grass[i].first > Actor1[j] && grass[i].first < Actor1[j+1]) { long long dist1 = abs(grass[i].first - Actor1[j]); long long dist2 = abs(grass[i].first - Actor1[j+1]); if(dist1 < dist2) { segments.push_back({grass[i].second, 1}); } } } } sum = 0; for(int i = 0; i < num; i++) { if(grass[i].first > Actor1[actor1-1]) { sum += grass[i].second; } } if(sum > 0) segments.push_back({sum, 1}); } sort(segments.begin(), segments.end(), greater<pair<long long,long long>>()); long long ans = 0; for(int i = 0; i < min(actor2, (int)segments.size()); i++) { ans += segments[i].first; } cout << ans << endl; return 0; }
|
非常朴实的vector开数组,限定条件——最后发现只能过一个点,剩下的全部超时。当我优化时间复杂度后发现剩下的超时全部报错。让我明白了简单的约束并不能拯救我的分,唯有高级算法才是唯一出路。
搓不出来经典“Orz”看大佬题解,发现了operator重构这个写法。
一、什么是操作符重载?
操作符重载,顾名思义,就是为自定义类型赋予标准操作符的行为。换句话说,你可以定义“加号”、“等号”、“乘号”在你的类对象之间应该做什么。
举个简单的例子(“+”的重构):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <iostream> using namespace std;
class Point { private: int x, y;
public: Point(int x = 0, int y = 0) : x(x), y(y) {}
Point operator+(const Point& other) const { return Point(this->x + other.x, this->y + other.y); }
void display() const { cout << "(" << x << ", " << y << ")" << endl; } };
int main() { Point p1(2, 3); Point p2(4, 5);
Point result = p1 + p2;
cout << "p1 + p2 = "; result.display();
return 0; }
|
我们重构(operator)了**’’+”,指定了p1和p2类型为(x, y)** 。此时的+不等同于普通的”+“,而是被定义为**(x + other.x , y + other.y)** 的**result(p类)**。
result是Point 类,其下的display 我们用**result.display ( )**引用。相 **”+”**的操作已在Point result = p1 +p2;
中完成,此时输出display中cout << "(" << x << "," << y << ")" << endl;
最后的结果如下图
我们再看一下比较难的例子,取自菜鸟教程的重构例子。当时我第一次了解重构并看了这个例子一头雾水,现在我们一起重新看一下它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include <iostream> #include <vector> using namespace std;
class Obj { static int i, j; public: void f() const { cout << i++ << endl; } void g() const { cout << j++ << endl; } };
int Obj::i = 10; int Obj::j = 12;
class ObjContainer { vector<Obj*> a; public: void add(Obj* obj) { a.push_back(obj); } friend class SmartPointer; };
class SmartPointer { ObjContainer oc; int index; public: SmartPointer(ObjContainer& objc) { oc = objc; index = 0; } bool operator++() { if(index >= oc.a.size() - 1) return false; if(oc.a[++index] == 0) return false; return true; } bool operator++(int) { return operator++(); } Obj* operator->() const { if(!oc.a[index]) { cout << "Zero value"; return (Obj*)0; } return oc.a[index]; } }; int main() { const int sz = 10; Obj o[sz]; ObjContainer oc; for(int i = 0; i < sz; i++) { oc.add(&o[i]); } SmartPointer sp(oc); do { sp->f(); sp->g(); } while(sp++); return 0; }
|
前面的步骤相同,不同的是利用看起来更高级的创建方法,不在public内直接定义未知数的值,而是 用int + 类名 + :: + 变量 + 定义值。此类做法始
1 2 3
| class Obj { static int i, j; };
|
这只是声明了两个静态变量 i
和 j
,告诉编译器这个类有这两个静态变量,但没有为它们分配内存。因为静态成员属于类而不是某个对象。普通成员变量每个对象一份,编译器可以在构造对象的时候分配空间。但静态变量是类“共有”的,所以必须由程序员在类外手动定义、初始化,才能真正分配内存空间。
1 2 3 4 5 6
| class ObjContainer { vector<Obj*> a; public: void add(Obj* obj) { a.push_back(obj); } friend class SmartPointer; };
|
a
:一个 Obj*
类型的 vector
,用于存放指向 Obj
的指针。
add()
:将对象指针添加到容器中。
friend class SmartPointer;
:授予 SmartPointer
类对其私有成员的访问权限。