codeforces #296 div2 (527C) STL中set的运用
题意:在一块H*M的玻璃上每次划一刀(仅仅能水平或竖直)。输出每次划开之后剩下的玻璃中面积最大的一块的面积。
做题的时候。觉得这么大的数据量,有每次查询输出,应该是数据结构的内容。
这道题能够用STL中的set容器来非常好地解决~set容器其本身就是用红黑树这样的数据结构来实现的。所以和原来的推測并不相悖。STL平时用的并不多。里面的一些函数非常生疏,熟悉一下
解题思路:
首先建立两个set型容器 ,每次分割都将分割的位置h或w插入到set中,因为set可以自己主动排序。运用两个函数lower_bound()和upper_bound()就行找到 和所插入的位置 前后相邻的两个已经被分割的位置,从而得到此次分割后新增的两个空间(见代码);
在建立两个set容器用来存最长的水平距离和最长的竖直距离,每次在插入两个新的距离元素的时候同一时候删除掉之前的大的距离元素。
另外。关于lower_bound()和upper_bound()函数:
iterator lower_bound( const key_type &key ): 返回一个迭代器。指向键值>= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值> key的第一个元素。
关于rbegin() 和rend()
rbegin() 返回的是反转set之后第一个元素的位置,也就是说*rbegin() = set中最大的元素;
rend()同理。
他们的迭代器是:
multiset<int>::reverse_iterator
rit;
code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int W, H, N; cin >> W >> H >> N; set<int> h, w; multiset<int> mh, mw; h.insert(H); h.insert(0); w.insert(W); w.insert(0); mh.insert(H); mw.insert(W); set<int>::iterator l, r; while (N--) { char c; int x; scanf(" %c %d", &c, &x); if (c == 'H') { l = h.lower_bound(x);///找到第一个 >= x的位置 r = l; l--;///迭代器向左移一个 h.insert(x);///插入新的分割线 mh.insert((*r)-x);///添加新的距离元素 mh.insert(x-(*l));///添加新的距离元素 mh.erase(mh.find((*r)-(*l)));///删除旧的距离元素 } else { ///以下凝视同上 l = w.lower_bound(x); r = l; l--; w.insert(x); mw.insert((*r)-x); mw.insert(x-(*l)); mw.erase(mw.find((*r)-(*l))); } ///用最大的水平长度 * 最大的竖直长度 = 最大面积 ll ans = ((ll)(*mh.rbegin()) * (*mw.rbegin())); printf("%lld\n", ans); } return 0; }