wssb

1. 除非是固定写法,不然不要为了省事就直接将好多变量写在一个struct里,尤其是再算最大值和次大的时候。

CF685B
num不应该变。

struct node{
	int bh,num;
}a[300005];
node qwq(node A,node B){return A.num<B.num?A:B;} 
/*~~~~~*/
a[now]=qwq(a[now],{ls,max(a[ls].num,siz[now]-siz[ls])});

2. 长链剖分一般用于优化树上dp,特别是dp状态某一维与深度有关。

eg:[CF1009F]

(https://www.luogu.com.cn/problem/CF1009F)

3. 指针有着独有的优越性。

题目见上条,共享内存可以用指针轻松实现,不仅可以省下空间,还可以省时间。

具体实现时要注意,指针数组只是指针,只能存位置,空间要另开一个数组,然后将指针数组指向所需空间的开端。

4. 最小生成树,对于权值相同的边,加入顺序没有区别(加入后形成的联通块组合一样)。

原因是:

  • 同一个图对于任意权值的边,所有最小生成树中这个权值的边的数量是一定的。
  • 对于任意正确加边方案,加完小于某权值的所有边后图的连通性是一样的

所以在考虑某一条边在最小生成树上出现的必要性的时候,可以对于权值相同的边统一考虑,且不同权值的边之间没有影响。

CF891C

5. 对于vector的边界

vector<int>ask;
/*………………*/
k=ask.size(); 
do
{
	/*………………*/
	now++;
}
while((now<k)&&(ask[now].w==ask[now-1].w));

首先,由vector的性质决定,now如果大于k,则会导致RE。

所以像如下的写法就会寄掉:

while((ask[now].w==ask[now-1].w)&&(now<k))

但是由于&&的性质, \(now<k\) 在前就会提前终止,不会出问题。(这也是一个卡常小技巧)

6. RMQ在写的时候一定要好好关注边界问题

尤其是一些奇怪的\(+1\)或\(-1\)。

7. 斐波那契数列性质

\[f_1=1,f_2=1 \]

\[f_i=f_{i-1}+f_{i-2} \]

经过展开归纳可得广义斐波那契 $ a_i $ :

通式:

\[a_i=a_1 \times f_{i-2} + a_2\times f_{i-1} \]

求和:

\[\sum_{i=1}^{n}a_i = a_{n+2} - a_2 \]

将通式带入后可得:

\[\sum_{i=1}^{n}a_i = a_1\times f_n + a_2\times (f_{n+1}-1) \]

8. 可持久化可以有效解决区间操作

对于区间操作,可以使用可持久化数据结构,$ [ l , r ] $ 可以变成对于 $ r $ 版本查询,然后再查询时当前节点记录 $ l-1 $ 和 $ r $ ,之后 $ sum[r] - sum[l-1] $ 就是 $ [l,r] $ 的答案。

9. 询问前k个最大的区间。

询问前k个最大的区间,可以将n种 左/右 端点不同的区间以三元组 $ (i,l,r) $ 的形式扔进堆中,每拿出一个所要求的的最大的,然后将 $ (i,l,w) $ 和 $ (i,w+1,r) $ 扔入堆中。

P2048超级钢琴

P5283异或粽子

10. \(Trie\)树一定要想清楚起始的\(num\)

建议从 $ 1 $ 开始,因为有时候可以直接跳到 $ 0 $ ,减少因为边界问题导致的出错。

11. 可持久化数据结构空间需要 $ O(nlogn) $ !!!

12. 一定要时刻牢记线段树的性质

$ pushup $ 使用子树的信息更新 $ now $ 的答案,直接更新,不要比较!!!

尤其是动态开点,一定要维护好边界。

凡事仔细思考,想明白之后再写!!!

CF1221F

13. 空间一定要开好!

数组开空间的时候一定要开够,并且算清楚在开够了的情况下会不会超空间。

如果会,那就要考虑离散化或换方法。

不要最后因为空间问题 $ RE $ 或 $ MLE $ 导致失分

CF1221F

14.十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

14.十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

14.十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

十年 $ OI $ 一场空,不开 $ long long $ 见祖宗

15. 注意,由于 $ luogu $ 特性,有时候数组开小了报错会是 $ MLE $

是的没写错,就是开小,报错 $ MLE $ ,离谱。

P4768

16. 在为了省事就将 $ A $ 变成 $ -A $ 之后排序得到降序排列时,时刻牢记用的时候是加是减。

17. 有返回值的函数一定时刻记得写 $ return $ !!!

18. 还是线段树qwq

在 $ JS() $ 时一定记得诸如 $ t[now].mmax $ 之类的都和 $ l,r $ 一样要在 $ if $ 之外初始化。

19. 提交之前无论改了什么都要记得测一下所有的样例!!!

20. 注意求最大和次大时,是否要求不同子树。

CF337D

21. 开 $ long long $ 有时候反而会见祖宗

22. 树形 $ dp $ 考虑状态转移时,要考虑的是如何将新的子树合并到已经有之前的子树信息的父亲上。

23. 因数定理:

若 \(x\) 分解质因数结果为 \(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),令\(f(x)=(k_1+1)(k_2+1)\cdots (k_n+1)\),则 $ f(x) $ 即为 $ x $ 的因数个数。

证明:

设 $ k\mid n $ ,则 $ k=p_1{b_1}p_2\cdots p_n^{b_n}$ ,则 $ b_i $ 的取值方式有 $ k_i+1 $ 种,所以 $ f(x)=num(k) $

24. a^b<=a,b

25. 在使用杨辉三角解决 $ C(n,m) $ 时, $ n,m $ 记得 $ +1 $

26. 隔板法

$ n $ 个球,放入 $ m $ 个桶内,可以空:$ C^{m-1}_{n=m-1} $

27. 二分要首先找到一个有单调性的东西,然后将它转化成可以快速判断的形式。

P1570 P1638

28. 关于取模

在做和取模有关的内容时,注意鸽巢原理的性质。

P5635

29. longlong取极小值时必须要写够长度,不然会变成大值。

30. 记忆化搜索记录状态或定义dp含义

在记忆化搜索记录状态或定义dp含义的时候,可以合并同类型的物品。

P2476

31. 分数相加

当需要多个数组合成某个数的时候,因为分数会约分,所以不方便剪枝,可以考虑将多合一转化为一个个减去得零。

P1763

32. scanf狗都不用

\(getchar\) 是可以读入 \(EOF\) 的,所以在以 \(EOF\) 结束的程序能直接 \(read()\) 就直接 \(read()\),但是同样对于字符,\(scanf(\%c,\&g)\) 会读入空白字符,只有 \(scanf(\%s,str)\) 才可以读到空白字符久停止。

综上,要么直接自己写 \(get()\),要么:

char g[5];
……
while(scanf("%s",g)!=EOF)

33. 01bfs

\(01bfs\) 只有在通过 \(0\) 边转移的时候才保证以后不会有更优的。所以只有在通过 \(0\) 边转移的时候,才可以 \(ck[now]=1\)。

同时,在通过 \(1\) 边转移的时候,需要判断大小在转移,\(0\) 边直接转移,一定不劣。

AT_arc084_b

34. 折半搜索

在折半搜索的时候,可以先对初始数组排序并处理,使得其尽可能平均,稳定合并的复杂度。

CF912E

35. 二分

对于 \(k\) 小值一类的问题,优先考虑二分。

CF912E

36. byd dev

时刻谨记加了 \(inline\) 的函数检查是否写了返回类型

37. 关于桶

关于桶的使用,在统计整个子树中的答案时,可以记录桶在初始和遍历完整个子树之间的差值,这样就可以省掉清空,极大方便了合并。

P1600

38. A=B \(\xRightarrow{}\) A-B=0

在求分组之后相等的时候,可以转化为相减为 \(0\),方便求解。

即为可以对于需要分组的数分配权值\(1\)、\(0\)或\(-1\),直接累加,就代表“选”“不选”“放在另一组”。

P3067

39. 牺牲时间换空间

在空间不够用的时候,可以考虑用时间来换空间。

如P4467

对于这种桶内的内容物逐渐扩大的形式,可以只记录有哪些被标记了,之后在用的时候,将整个桶重建一遍。

40. max min

在做题目的时候不要看到 \(max\) 和 \(min\) 加加减减就想差值最大最小,也有可能就是单纯的全翻倍之后答案不变。

CF1473E

41. 分层图

在跨图的时候由于1节点的特殊性(经过的边数过少,导致不够分层),经常会特判直接转移到1的点。

但是有些时候其实可以直接在不同层之间的相应节点间连一条长度为0的边就好了。

CF1725M

42. 我再把m打成n就直接趋势吧

43. 特殊的边权转化

P2916

44. 在矩阵过大的时候可以考虑将矩阵映射成一维数组

P9641

45. 区间操作

无论是区间的什么操作,转换成前缀和或者差分数组都是好的。

P5937

46. 输出之时

我再在输出longlong的时候用%d我就是狗

47. swap()

inline void swap(int &x,int &y){x^=y^=x^=y;}

48. 区间dp

区间dp初始化的时候,尽量尽可能多的初始化最小的单位,不然容易被更小的单位错误覆盖。

49. 没有人规定,答案和答案的个数要一起统计。

CF1088E

50. 离散化之后,数据范围变成了cnt而不是n!!!

50. 离散化之后,cnt的上限要\(\times\) k,!!!

51. 倍增的时候数组最好要开两倍,防止特判少而导致RE

倍增的时候要么时刻特判,要么容易RE。如果不特判的话,在向后+(1<<i)容易越界。

52. dp优化

\(dp\) 的时候如果状态只是记录可行性,可以考虑将某一维变成存储的值,记录在可行的条件下最优情况。

53. tarjan

有向边的tarjan求强连通分量要判断是否在栈中,然后再更新low!!!!

有向边的tarjan求强连通分量要判断是否在栈中,然后再更新low!!!!

有向边的tarjan求强连通分量要判断是否在栈中,然后再更新low!!!!

posted @ 2024-07-11 14:57  YT0104  阅读(107)  评论(0)    收藏  举报