Point 1

\(\text{CodeForces - 543D Road Improvement}\)

正确写法:

for(int i = suf[u].size() - 2; i >= 0; -- i)

错误写法:

for(int i = suf[u].size() - 2; ~i; -- i)

原因是 ~\(i\) 只能判断 \(-1\) 的情况。

Point 2

关于类 set, map 的东西,如果把结构体装在里面的话,需要把 所有元素都设一个偏序,否则可能出现不相同的两个数据被去重。

Point 3

今天才知道两个数据类型相乘并不是得到前面的数据类型?而是得到 精度更高 的类型。以后还是要小心这类转换吧。

Point 4

对于边的遍历:

void dfs(int u) {
	vis[u]=1; siz[u]=1;
	erep(i,u) {
		if(vise[i]) continue;
		vise[i]=1;
		dfs(v);
		ans+=w[i]; siz[u]+=siz[v];
		ans1=u,ans2=v;
	}
}

这样不是 \(\mathcal{O(n)}\),应该还差得远。因为会有回退,判断时还会遍历边。

Point 5

判断到达叶子节点直接 \(\rm return\)(前向星)。

曾经的写法:

if(nxt[head[u]] == 0) return;

其实就是判断是否只有一条边连接。然而……根节点也可能出现这种情况,然后就凉了。

正解:

bool flag = 0;
for(int i = head[u]; i; i = nxt[i]) if(to[i] != fa) DP(to[i], u), flag = 1;
if(! flag) return;

Point 6

依稀记得这个错误在写 \(\text{fwt}\) 的时候也踩过。

当模数为 \(998244353,10^9+7\) 之类大质数时,不能直接写:ans = (x*2+y)%mod,会爆 int(很弱智是不是)。

哈哈,最近犯了个差不多 sb 的错误 😅😅😅。差不多是做 \(a\times b\)\(a,b\) 均为 long long),结果 \(b\) 没有取模,然后就寄了 😅😅😅。

Point 7

明明我知道这件事……但真的调起来很救命啊 〒▽〒!

关于 \(\text{memset},\text{memcpy}\) 这一类函数,最后是 \(\text{sizeof(type)}\cdot \rm len\) 啊!啊!啊!

今天手写 \(\rm bitset\) 调得想哭😢。

Point 8

2020 牛客 NOIP 赛前集训营-S(第一场)- C 牛牛的凑数游戏

Point 9

关于高精除的问题。调这个锅直接去世

fep(i,p,1) a[i-1]+=a[i]%div*10,a[i]/=div;
while(p>1&&a[p]==0) --p;

你会发现,\(a[0]\) 存的是真正的余数乘 \(10\),所以一定要记得除。

Point 10

我真的要哭了!调了这么 jb 久,结果是倍增数组下标写反了,焯!

此时无声胜有声!

Point 11

\(\text{random_shuffle()}\) 记得加随机化种子!

Point 12

发现结构体初始化函数 \(\text{node}()\{\dots\}\) 如果名字和此结构体名字不一样也不会报编译错误?

然鹅就不会给你初始化……

还有一件奇葩事是结构体内可以开不定长数组,但是会跑得贼慢……

Point 13

想题之前记得算一遍样例。

Point 14

注意自己设的极值不要加爆了。

Point 15

至今未弄懂结构体……

这题\(\text{ 22pts }\)wa 成 sb.

然后发现这样写在洛谷都是 wa 的:

struct buy {
    int s, v, t;
    buy():s(),v(),t(){}
    buy(int S, int V, int T):s(S),v(V),t(T){}
};

struct buy {    int s, v, t;    buy() {}    buy(const int S, const int V, const int T) {s = S, v = V, t = T;}};

真的很绝望。

然后这两种都是可以过的:

struct buy {
    int s, v, t;
    void init(int S,int V,int T) {
    	s=S; v=V; t=T;
    }
};

p[i]=(buy){...};

关键是上面 4 种写法在 \(\sf darkbzoj\) 里都是对的 🙃。

以后还是直接写函数吧 🙃。

Point 16

使用这两个函数之前要排序!
\(\text{upper_bound(begin,end,val)}\):从数组的 \(\rm begin\) 位置到 \(\text{end}-1\) 位置二分查找第一个大于 \(\rm val\) 的数字,找到返回该数字的地址,不存在则返回 \(\rm end\).
\(\text{lower_bound(begin,end,val)}\):同理,为大于等于。

注意减的时候减去开始位置。

另外与其联动的还有 \(\text{unique()}\) 函数,需要注意它并不会 真正删除 重复的数值(使用之前也 需要排序)。所以如果想用 \(\rm auto\) 的话,对于 vector 还要加一个:\(\text{vec.erase(unique(values.begin(), values.end()), values.end())}\).

另外结构体使用 \(\rm unique()\) 需要注意要重载 == 号!

Point 17

写数据结构时要判断节点是否为空。

Point 18

回收节点请全部清零。

Point 19

一定要给 bool 变量赋初值!

Point 20

关于结构体内存对齐。

  1. 除了第一个成员变量,其他变量要对齐到 对齐数 的整数倍的地址处。
  2. 对齐数:编译器默认对齐数与该成员大小的较小值。在 \(\rm linux\) 中默认对齐数为 4.
  3. 结构体总大小为最大对齐数的整数倍。

比如这个结构体:

struct node {
    char a;
    double b;
    int c;
};

最终就是这样:

当然在实际生活中可以直接用 \(\rm sizeof\) 嘛。

Point 21

虽然可能没有什么用……但这个错误真的找了很久……
我的代码 在这组数据上会错,原因是不去括号与前面的符号没法提前算。

!(F|F)|(V)

再放一个比正解还要麻烦的 数据生成器

Point 22

在写有返回值的函数时,请注意是否有调用下一层函数后需要改变的值。

Point 23

负数在用 \(/x\) 时是向零取整。

Point 24

关于三目运算符:

condition?do A,do B:do C,do D;

此条语句的意思是如果满足条件就做 \(\text{A, B}\),反之做 \(\text{C, D}\).

不过事实上,编译器会判定成这条语句:

(condition?do A,do B:do C),do D;

也就是说无论如何都会做 \(\rm D\)。解决方案是将它们括起来。

Point 25

这个真的傻了。在 \(\sf Luogu\) 上 MLE 疯了,结果其实是数组没开够。

(╯‵□′)╯︵┻━┻

还有,一条线段在线段树上分成的区间个数是 \(2\log n\) 的。

Point 26

我最终还是写了如何算内存

\[\text{1 GB}=1024\text{ MB}=1024^2\text{ KB}=1024^3\text{ B(byte)} \]

或者直接用 \(\rm sizeof\),算出来的是 \(\rm B\).

Point 27

\(\text {Dev-C++}\) 很神奇的一点就是不会将这个玩意报错:

inline Max(int x,int y) {
	return x>y?x:y;
}

然后就成功 CE 了。

Point 28

用 STL 时,在减小迭代器时一定要记得检验是否为 \(\rm begin()\)

Point 29

对于 string 类型,+= 相当于扩位操作,一开始只有赋值足够的位数,才能在后面使用 [] 赋值与访问。

Point 30

血的教训!前向星的 \(\rm head\) 数组以后都清 \(-1\) 了!抱着一个 \(\rm dijkstra\) 模板调到哭!

Point 31

做有标号的题目时,要时刻记住前后是否排序,标号是否正确。

Point 32

按理来说不是坑的……但调太久了必须放在这儿警醒自己。

关于扫描线:将元素离散化之后必须用一个点维护一段区间(比如点 \(1\) 维护 \([1,2)\)),对于节点 \([l,r]\) 应维护区间 \([h_l,h_{r+1})\),否则会出现 \(\text{mid}\)\(\text{mid}+1\) 之间的区间没有被维护的情况。

Point 33

汗如雨下了属于是 😅。

\(\text{POJ - 1742 Coins}\) 明明是 \(\mathcal O(nm)\) 的单调队列优化 \(\mathtt{dp}\),结果 TLE 麻了。

跟我说这个跑完全和 01 背包不行我就认了,结果还是 TLE。笑死,最后把队列改成数组就过了,这什么 ** 玩意儿。

后记:一次模拟赛又被队列常数卡了,以后感觉卡常就手写循环队列吧 qwq.

Point 34

\(\rm NaN\)\(\neq\)\(\rm NaN\)

具体可以看 这个,简略地说就是零与无穷、无穷与无穷看似计算出 \(1,-1,0\) 这种数都会导致 \(\rm NaN\).

Point 35

在 vector 的遍历过程中加入元素,就像凌晨三点的 emo,就像鱼在陆地上无法呼吸……希望你永远也不要懂我的痛……💔

Point 36

不要在循环中定义 string 或 vector 之类未经编译器优化的类型,否则会降低运行效率。

Point 37

例如宏定义

# define min(x,y) (x)<(y)?(x):(y)

# define 的实现与函数的实现机制不同,只是简单的代码替换,所以若参数 \(x\) 为函数,在计算的过程中会被调用两次,这在递归函数的使用中是非常致命的。

Point 38

血的教训*2!非 void 函数一定要写返回值,不然可能会出现很奇怪的问题,这时你的代码会像一坨屎一样好调。

Point 39

在用阶乘求组合数时一定要判断 是否存在逆元!一种容易被忽视的情况是 \(p\) 为质数,但是 \(n\) 可能大于 \(p\),此时要用 \(\rm Lucas\) 定理计算组合数。

Point 40

我真的要吐了,今天调一道整体二分的板子题调了整场比赛,不知道自己在写什么,最后发现自己对线段树的理解一直有问题 —— 左半拉明明是更大的!焯!

Point 41

是右边的光头强贡献的菜品:对于某个函数的特判,一定要分清先后顺序!就比如线段树的无解与叶子节点的优先级问题。

Point 42

血的教训*3!我就问你,"\(\text{[BZOJ 4212] }\)神牛的养成计划",对得起我们吗?一个可持久化 \(\rm trie\) 的锅都测不出来,日内瓦退钱 🤬!

在插入字符串时,结束字符一定还要继承祖先的儿子!否则先插入 UU 再插入 U,之后的插入根本不会统计 UU 这个前缀!

void ins(int ID) {
    int n=str[pa[ID]].length(), pre=rt[ID-1], p; 
    p = rt[ID] = ++cnt; sz[p]=sz[pre]+1;
    for(int i=0;i<n;++i) {
        int d=co[str[pa[ID]][i]];
        for(int j=0;j<4;++j) 
            if(j^d) t[p][j]=t[pre][j];
        t[p][d] = ++cnt;
        sz[t[p][d]] = sz[t[pre][d]]+1;
        pre=t[pre][d], p=t[p][d];
    }
    for(int j=0;j<4;++j) t[p][j]=t[pre][j];
}

Point 43

线段树区间操作要记得判断 \([L,R]\) 区间是否满足 \(L\le R\),不然会出很多玄学错误 qwq.

Point 44

竟然现在才写出来这个锅!最好将 \(\rm root\) 的深度和空节点的深度进行区分,否则可能会发生奇怪的问题。

e.g. 倍增求 \(\rm lca\) 就会跳出 0.

Point 45

最近新创了很多菜品昂 qaq!其实也犯过很多次了,就是计算出 \(\displaystyle s=\prod a_i\),想要逆推一些 \(a_i\) 的乘积,一定要注意 是否有逆元!更具体地说,一定要注意是否存在 \(a_i=0\)

posted on 2020-06-05 21:34  Oxide  阅读(234)  评论(2编辑  收藏  举报