考场tips

又:奇怪挂分点 或 做题手法

1.调和级数O(n/1+n/2+n/3+...+n/n)=O(nlogn)

2.树上问题中边和点的相互转化,染色,多次查询树剖+线段树。

3.3221225477 (0xC0000005): 访问越界,一般是读或写了野指针指向的内存。
3221225725 (0xC00000FD): 堆栈溢出,一般是无穷递归造成的。
3221225620 (0xC0000094): 除0错误,一般发生在整型数据除了0的时候。

4.恰好与至少的相互转化,容斥原理或二项式反演。

5.用 vector().swap(v)可以释放v的内存。

6.根号分治的想法。主要在于观察题目条件,得到暴力美学的做法,经常和操作次数、操作方式和每次操作值域有关。比如 排列最小生成树 (pmst) ,想到 \(|i-j|*|p_i-p_j|\) 超过n是不优的,又有排列的条件,从而得到操作不超过根号n条边。又比如 CF1207F Remainder Problem ,经典应用吧,对于小于根n的位置维护 \(b_{i,j}\) 表示当前所有下标模i的结果为j的数的和,对于所有大于根n的位置,直接在询问答案时暴力枚举下标,均摊复杂度 \(O(q\sqrt{n})\) .

7.枚举子集的子集的时间复杂度是 \(O(3^n)\) ,可以把式子展开使用二项式定理证明。推广:枚举k次子集的时间复杂度是 \(O((k+1)^n)\) .

8.永远写不对的dijkstra……(和现在已经不会写的SPFA)要关注两个算法的适用范围,还有vis,以及加入队列的-dis。仔细检查最短路!还有如果在外面更新了dis,那么一定要把当前点入队,才能去更新别的!!!这是动态转移和floyd的区别之处。

9.读题读题读题,审题审题审题!!!题目条件一定要看清楚再写,可以把条件或者自己想到的东西先写到本子上,写代码的时候一定要关注。题面看不懂就多看几遍,一个词一个词的看,尤其是t1t2不能因为看不懂而不写。多读题多读题,题读百遍其义自见。

10.容斥原理,二项式反演,至少/至多和恰好的转化。还有写的时候注意组合数和快速幂的正确性。

11.一定要判无解!!!!

12.最短路问题,如果要考虑一些性质,可以建立最短路树,如果最短路不唯一,则是最短路图。

13.双指针,把O(n^2)等转换为O(n). 数据结构枚举左端点查询右端点,或者扫描线维护二维结构。

14.平面图和对偶图的相互转化。简单来说(可能不严谨),平面图是边将图划分成为若干个不相交的面(比如网格),对偶图是把平面图的每个面化为一个点,如果两面相邻,则对该两点连一条边。经典手法是求平面图的划分数等价于对偶图的路径数。

15.快排重载运算符的时候不能加等号,比如写<=就容易re,要写成<。本质上是由于快排的内部程序结构中while引起的。

16.关于质因数分解的常用结论:一个数所含质因数最多log级别。(质数>=2)

以及卡常小技巧,特判2,然后从3开始,i+=2,只考虑剩下的奇数

17.vector加sort比set快很多!

18.像存权值这种可能相等的东西,一定要用multiset!并且每次删除元素一定要按照地址删,如果按照权值删,会把所有当前权值的都删掉。

19.图的边权形如|i-j|的直接贪心走/连相邻标号节点!

20.一旦题目和什么gcd或者质因数分解有关,一定要注意其情况数上界很有可能是log级别的。甚至于有方法是枚举答案去check。

21.分解质因数和寻找因子的最坏复杂度都是根号。

22.优先队列重载运算符,注意要重载小于号。

struct node{
    int x;
    int y;
    bool operator<(const node &a) const
    {
        return x>a.x;//从小到大排序
    }
};

23.算空间!!一旦开大直接->0pts!!!

24.对于只有加操作并需要取模的dp,当时限很紧时,不要开longlong+手写取模+快读!!

25.对于只有三种不同颜色去排列的方案,dp时一定要记得设上一次出现的位置为i,j,k,再根据下一个放什么去转移!(同类型的题目见一次不会一次,真服了)

26.取模取模取模!!即使是部分分也要记得取模!

27.对于计算本质不同的子序列,可以 \(O(n^2)\) \(dp\),设 \(dp_i\) 表示以i结尾的本质不同的子序列个数。转移时钦定只对它靠一侧的匹配转移。

可以优化到 \(O(n)\) ,即设 \(dp_i\) 表示以 \(\leq i\) 结尾的本质不同的子序列个数。但是两种写法一定要分清楚不要混了。

28.一定要加c++14编译环境,以及开大栈空间!-std=c++14 -Wl,--stack=100000000

29.关于异或运算的处理手法,问到大于小于的问题一定要想到一定是:前k位相等,第k+1位不等。而且很多异或的条件可能只是和相邻两项有关,这个细节也是很好用的。可以考虑01trie(当然能简单维护就不要复杂化)。

30.对于每个区间求方案数或者贡献的问题,套路性地把某个点i固定下来,然后对它求贡献,可以用数据结构维护。

31.大量访问时建议使用vector而非链式前向星,因为vector的下标连续,在常数上更优!否则会被卡常!!!

32.二维数组一定要把大的那一维放前面,小的放后面,会快很多。

33.对于求一个字符串满足某些区间内0和1数量相等,不防记0为-1,记1为1,求前缀和,则该区间前后sum相等。或者直接0当0,1当1,然后列出来题目限制的若干条件。

这东西叫 差分约束系统 。对于每个约束条件 \(x_i-x_j \leq c_k\) ,都可以变形成 \(x_i \leq x_j + c_k\) ,这和单源最短路中三角形不等式非常像。那么我们把每个变量 \(x_i\) 当作图中的一个节点,对每个约束条件,从节点j向节点i连一条长度为 \(c_k\) 的有向边。(带绝对值就是双向边,注意对于本题还要建立原本的 \(|d_i-d_{i-1}|=1\)

注意到,对于一组解 \({a_1,a_2,...,a_n}\) ,对于任意常数d, \({a_1+d,a_2+d,...,a_n+d}\) 也成立,因为做差后d刚好抵消。

过程:设dis[0]=0并向每个点连一条权重为0的边,跑单源最短路。若图中存在负环,则给定的差分约束系统无解。

34.卡时的时候一定要写成(double)clock()/CLOCKS_PER_SEC转化成秒,因为本地和评测机的这个周期不一定一样!虽然也不是很理解这个为什么要加double,但是不加绝对会挂!

35.一定要看是否要开long long或者__int128 !!! c++14允许使用__int128了!注意手写输入输出。但是如果范围超过__int128就要写高精了。

36.场上一定要先看四道题,避免死磕一道把时间浪费完了。难度可能不是顺序。遇到简单的部分分也可以先写。(我就只有这一场不是开始先看全部的题,结果就今天不是顺序。。。)

37.看时限,看空限,即使是部分分也要看!有时候题目会给出很奇怪的时空限制!比如4000ms,16MiB之类。。甚至于会有非常小范围的n,k这种,直接暴力会比带值域log快!!注意卡时

38.能直接推导就不要过分转换,否则边界之类的分讨很麻烦。(一旦转换就要注意边界条件)

39.草稿上不要太凌乱,适时想想有没有脑中一闪而过又忘记的东西,注意把想到的都记下来。

40.checker 的使用方法。把所有东西放到同一个文件夹,在“此电脑”中打开,并在上方地址栏输入cmd,然后按照题目格式放入checker和in/out文件。

另外,构造题先研究样例输出,先试图瞪出规律。否则构造还是需要严谨。

41.启发式合并的想法,有时候有题目需要维护集合,并且合并顺序可以自定,那么把小的向大的合并,是O(nlogn)的。会很方便。理解上就是,每产生一次合并,集合大小至少翻倍,那么对于n个集合,每个集合最多参与log(n)次合并。

42.bitset奇妙函数:

for(int j=tmp._Find_first();j<=m;j=tmp._Find_next(j))
//可以遍历其中所有的1的位置

b.count();
//计算其中1的个数

43.能少取模就少取模,能不开longlong就不开longlong,小心t飞。但是别忘了可能越界的地方要*1ll,相减要+mod !!!

44.一般遇到瓶颈,想不到算法或者怎么维护的时候,大概率是题目性质没发现完全。多读题多手算样例,挖掘题目本身。反正如果真是什么手法算法没想到,那肯定是我不会的东西啊,场上也不可能写出来

45.对于图上路径处理/找环的一个重要想法就是dfs树上,考虑树边、非树边(横插边、返祖边),打标记去判断。

46.经典手法,把排序或者比大小改成维护0,1,即比当前小的为0,比当前大的为1。(有时可以使用线段树维护01排序)

posted @ 2024-10-06 16:11  YYYmoon  阅读(13)  评论(0编辑  收藏  举报