刚做hihocoder #1086 Browser Caching的题,一开始的做法是stl unorderd_map+list,满心以为一次就AC,结果……TLE了。O(N)也能TLE!!(╯‵□′)╯︵┻━┻
看别人的讨论,这个算法思路没错啊!
捣鼓了老半天,换了map,TLE;cin/cout太慢,别人也用,也没见TLE……
后仔细看某人代码,发现他没用list的size()成员函数,而是加了另外一个变量int sz表示list的大小,于是怀疑list的size()有猫腻,先把我代码里的size()函数换成sz试试……果不其然,AC了<_<
运行时间由5000+ms 降到 300+ms,是个人都能想到size()有问题好嘛!随手抄起《STL源码剖析》,查看list的数据结构定义,看到size()成员函数定义如下:
size_t size() const
{
size_type result = 0;
distance(begin(), end(), result);
return result;
}
而distance函数,sgi stl官方文档说明其的时间复杂度:“Constant time if InputIterator is a model of random access iterator, otherwise linear time.” 而list是双向链表,其迭代器不是random access iterator,因此时间复杂度为线性时间复杂度。因此,sgi stl官方对size()函数如此解释道:“Returns the size of the list. Note: you should not assume that this function is constant time. It is permitted to be O(N), where N is the number of elements in the list. If you wish to test whether a list is empty, you should write L.empty() rather than L.size() == 0.”
这下子问题就昭然若揭了,果然是oj使用的stl版本实现里,list的size()成员函数时间复杂度是O(N)的。虽然有的stl实现版本里,list的size()是常数时间复杂度,但是像sgi stl这么流行的版本都是线性时间复杂度,如果对stl的实现不够了解的话,的确会掉到坑里也不知道怎么回事→_→
参考:
1. sgi stl list