自己犯过的错误与经验
1.关于swap复杂度问题
关于STL容器的swap复杂度问题,春节十二响题解里有人提到这句:
swap 在不开 C++11 的情况下是 \(O(n)\) 的,开 C++11 则是 \(O(1)\) 的,如果不开 C++11 可以记录 id 然后交换 id 。
本人当时做一道需要用启发式合并 \(set\) 的题,上洛谷发帖询问这个问题,结果得到的答案很不统一。
自己在本机测试了一下,结果开 C++11 和不开 C++11 速度是差不多的?
后来看了这篇:关于几类STL容器swap的复杂度问题
虽然不知道博主为啥 \(id\) 也叫 \(lyy\) 。。。
\(vector,map,set(multiset),deque\) 的 \(swap\) 复杂度:\(O(1)\)
\(priority\_queue,queue,stack\) 的 \(swap\) 复杂度:\(O(n)\)
特别要注意以上三种容器!!千万别在考场上写
春季十二响是堆的启发式合并,\(priority\_queue\) 的 \(swap\) 仿佛不开 C++11 是 \(O(n)\) 的,开了就 \(O(1)\) 了。
目前来看好像有 \(.begin()\) 与 \(.end()\) 函数的 \(STL\) 都能 \(O(1)\),而 \(queue\) 与 \(stack\) 没有,就得 \(O(n)\) 了,\(QwQ\)。
当然有的考试会开 C++11 ,但是为了安全起见,还是建议用一个 \(id\) 数组记录一下位置,交换的时候直接交换 \(id\) 。毕竟学OI这么短的时间,一共没几次考试,因为这样的错误导致正解或大部分的分数走掉,最后可能导致差一点达到预期目标,会留下很大的遗憾。
另外亲测 \(swap\) 两个一维数组永远是 \(O(n)\) 的,如果不是瓶颈复杂度可以交换,如高斯消元和后缀数组中的swap,否则还是记得开一个 \(id\) 记录位置。
还是菜啊~,博主不会写指针。。。要是会了估计就没这么多事了。。。
2.关于数组状态定义和枚举顺序的关系
今天模拟和别人写了同样复杂度的动态规划,几乎找不着不一样的地方,结果时间上差了好几倍导致T了。\(QwQ\)
既然是常数上的问题我就去考虑一些玄学的地方了,于是我想到了我枚举数组中的每一维的顺序是不是会对时间上有影响。
果不其然,就是这个问题。
159巨佬TQL!orz,日常膜拜。
int f[N][N][N],g[N][N][N],h[N][N][N];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
f[k][j][i] = g[i][k][j] = h[i][j][k] = 1;
意思就是说,上面的代码中,\(h\) 数组要比 \(f\) 或 \(g\) 数组访问地更快一些。
以后写动态规划题的时候要注意这一点。