杂项个人总结

· · 个人记录

留坑待填

多测不清空,爆零两行泪!

注意空间、注意CE

仔细读题,不要想当然!

仔细读题,不要想当然!!

仔细读题,不要想当然!!!

取模的题,输出时都加上%p+p%p

开变量时注意类型!!!区分intboolchar!!!

善于使用草稿纸,推式子,不要空想

int的inf和long long的一定要区别!!!好好想想inf的大小

注意看模数!!!

sort中,使比较函数 return 1的元素会往前;

priority_queue 默认大根堆;

数组开小了有时会MLE

读优会出现神奇的问题

迭代器的正确使用方法

vector<DataType>::iterator it =……;

vector使用技巧

vector<int>v;
v[1]=1;

此代码执行时会崩溃;因为初始时vector的size为0,无法储存任何值;

这时可以选择push_back()或resize(x);

如果不是强制在线,能不用priority_queue就用vector.sort,不然很慢;

注意memset的数组不要开太大;

printf的时候严格区分%d和%lld;

对于离散区间问题(比如数列问题),在拆分序列时注意边界问题,要+1/-1,不重不漏;

多组询问,一定要把每次的清零初始化做好!!!

如果枚举点对求贡献会T的话,不妨枚举每个边的贡献

注意DP时更新的顺序;

并查集可以在路径压缩的同时维护数据;

set维护的是最小值;

小数组不要在意大小,比如把字符映射到数组,数组起码开257;

向上取整ceil(n/m)=(n+m-1)/m

数组下标记得防越界,防负数;

正向进行操作很费劲?那就逆向试试

求XXX包含至少一个YYY的种类=XXX的种类-不含任何YYY的种类

注意int的inf和longlong的inf不一样,最好使用memset的无用位置

inf不要随便开,不要开太大,严格按照题目

右移时,如果超出int,务必1ll<<x

见到中位数,尝试二分答案

二分一个答案mid,将序列中所有小于mid的值赋值为-1,大于mid赋值为1,查询新序列有没有>=0的子段和,如果有,l=mid,else r=mid(+-1什么的具体分析);

不能用__int128

主席树的空间最好开200倍,越大越好

遇到各种弹出队列的情况,注意判空

能用数组不用结构体

给定一个序列,要求选出两个不相交的区间,使……

这样的问题往往可以转化为前缀后缀分别求一个区间,然后枚举中间点;

并查集处理区间问题

一定要f[n+1]=n+1

区间完全覆盖是find(1)==find(n+1),注意最后的+1;

在更新一个点的值时,如果稍后还需要用到它的原始值,就要考虑修改的顺序

使用set.lower_bound时,注意!=set.end()

将询问换成前缀和相减时,记得扩大存放询问的数组;

遇到区间问题,前缀和无法解决,往往采取分块的办法,块的大小视区间大小来定(区间定长当然更好)

在统计时,如果采用相对值难以统计、修改、转移,不妨改成绝对值

set.insert也有返回值:

std::pair<iterator,bool> insert( value_type&& value );

bool表示是否插入成功;

不过最好别用;

求倒序和时,一定要倒序维护!!!

set是去重的

线型基在成功插入后要写break!!!

注意double的负零

比较两个长度为6的数组是否可以通过翻转,循环移动得到对方

bool cmp(int a[], int b[])
{
    for(ri i = 0; i < 6; ++i)
        for(ri j = 0; j < 6; ++j)
        {
            bool ok = 1;
            for(ri k = 0; k < 6; ++k)
                if(a[(i + k) % 6] != b[(j + k) % 6])
                {
                    ok = 0;
                    break;
                }
            if(ok) return 1;
            ok = 1;
            for(ri k = 0; k < 6; ++k)
                if(a[(i + k) % 6] != b[(j - k + 6) % 6])
                {
                    ok = 0;
                    break;
                }
            if(ok) return 1;
        }
    return 0;
}

关于erase和iterator

1) 对于关联容器(如map, set,multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。

注意那个++,必须放在里面

set.erase(it++)

2)对于序列式容器(如vector,deque),删除当前的iterator会使后面所有元素的iterator都失效。这是因为vetor,deque使用了连续分配的内存,删除一个元素导致后面所有的元素会向前移动一个位置。还好erase方法可以返回下一个有效的iterator。

3)对于list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的iterator,因此上面两种正确的方法都可以使用。

printf 输出 “%”

使用两个%

cout 设置位数

cout << fixed << setprecision(2) << double <<endl;

warn: fix

hihocoder 1383

字典树,注意区分文件夹名和文件名相同的情况;

区分set和multiset!!!

dfs全局变量存储容易冲突。

重载小于号不能重载小于等于号

本地用bitset最好用set、test,可以报告re

无理数的高精度处理:保留“a+b*根号”的形式:构造有序数对:(a,b),即可定义乘法。

Linux 下使用 -fsanitize=address 可以查RE(G++ 4.8+)

在对网格图编号后,通过编号还原位置,最好直接开个数组记

Trick

异或打标记实现(带随机性)的状态相同性确定。

Random_shuffle

windows下random_shuffle很弱,只会改变前32767个位置。可以手写一个random函数。

A=1<<15|3,B=33333331,C=(C*A+B),这组的循环节2e9左右。

做题一定要先挑可做的做...

在continue或break循环的时候,记得想想有没有什么要做的事没做

取模计数题不要出现负数!!!

取模真的很慢!!!避免大量的较小数乘法的取模!尝试都用LL存下来最后同一取模!

double的0/0是UB!

比赛时随时做记录:哪道题可做,那道题的哪个可写的部分分没写。

随机生成树高比较高的树

每次rand一条边

快速幂的b不要爆int!

发现自己调题调不出来,看看自己的每个数组,是不是忘了赋值