注意事项·思路·好东西·黑科技

好东西

注意事项

代码实现

  • !!斜率优化dp,数论,数学题 开long long
  • 变量名取得Chinglish一些
  • !!!没开O2时慎用STL,尤其是set
  • 珍爱生命,远离STL::queue,vector比queue快得多
  • vector内存连续,开了O2尤其快,稠密图时写vector而不是模拟链表或邻接表
  • priority_queue比set快得多
  • 只要涉及乘法就应该警惕,考虑是否会爆int
  • 数位dp,如果有很多维0/1,写成循环而不是每个0/1大讨论转移
  • !!!动态点分治易错点:点分树上两点距离不能当成是边权相加
  • 多项式各种操作中,做乘法扩大次数界的前后,记得将超出部分清0
  • FFT空间开4倍
  • !!!回溯(比如分治)如果要用到数组开static!如果要使用全局变量一定要谨慎,考虑是否已经被修改
  • priority_queue是大根堆
  • 字符串哈希,字母不要对应成0!这样将无法区分ab和b
  • 字符串哈希的进制数设成质数!(质数的幂在模意义下更不容易重复)
  • 输出优化注意特判0
  • 线段树合并不能最后再求答案,必须每个点与其子树合并完立即求答案(意味着询问离线),否则该点信息会被修改。如果一定要最后再求(意味着询问在线),可以可持久化。
  • 变量名避免使用time,index;慎用x0,y0,next,last
  • 用memcpy时如果A,B两个数组size不一致会鬼畜!
  • 连通分量tarjan的时候记得要清空stack[top+1],否则退栈的时候比较会GG
  • 斜率优化DP的时候在写不等式的时候如果写成乘法,一定要写成<=或>=,因为如果一个数是0,导致斜率函数为0,判断的时候一直相等决策就会一直停在那个地方,然后GG
  • Splay的区间翻转操作,不仅要记得交换左右子树,有关左右区间的信息也要交换
  • Splay区间翻转时,如果涉及左右区间的信息的维护,就不能打成下面这样:
if(tag[x])
{
    swap(a[x][0],a[x][1]);//交换x的左右子树
    swap(lx[x],rx[x]);//交换x的左右区间的信息,例如lx[x]表示x的区间从左端点往右的最大连续和
    tag[a[x][0]]^=1,tag[a[x][1]]^=1;//下传标记
    tag[x]=0;//标记清空
}

为什么这样会错?尽管我承认暂时lx,rx的值都是正确的。但是一旦执行update(x),lx[x],rx[x]就由lx[lson],rx[rson]来更新
对x进行了翻转时,仅交换了x的左右子树,并没有交换lx[lson],rx[rson]
所以更新出来的x点信息是错的

  • Q:set怎么自定义优先级?
    A:(慎用!!)
struct set_cmp{
    bool operator ()(const int &x,const int &y){
        return dfn[x]<dfn[y];
    }
};
multiset<int,set_cmp> s[maxn];
  • 调试出现鬼畜情况,大概率数组越界。

算法易错点

  • 欧拉回路,走过的边要删除,否则若多次进入同一个点,每次扫一遍出边会TLE

策略

比赛策略

  • if(当前状态=稳扎稳打) then (写对拍) else if(当前状态=放手一搏) then (手出小数据+肉眼)
  • 能写线段树就不要写平衡树(树套树卡空间除外)
  • DP:如果发现转移很有问题,又确信没有其他做法,尝试更换转移方式。
  • 发现程序有bug,先不急着开始调,不管是WA,RE,TLE等,先检查一下是否是数组爆了,或是没开long long
  • 对于空间不大的题,数组开大几倍
  • 对于算法常数仔细考虑,不要轻易放过自以为会TLE的想法
  • 任何一道题(即使是暴力),想好算法、实现方法再开打
  • 调试的时候,如果为了调试修改了程序中的某一段,一定要打上注释,提醒自己调试完把程序变回去
  • 比赛剩余1个半小时的时候必须开打,不能再拖

学习策略

  • 多感性理解。

思路&套路

  • 决策可以看成点,也可以看成直线。当一种难做时,思考另一种
  • 图论(尤其网络流)常用套路:拆点,拆边
  • Q:什么时候用(双向)bfs,什么时候用(ID)A*?A:当状态空间不大时,用bfs。当解的深度不大,能设计启发函数,或者感觉bfs铁定超时,就写IDA*

  • 许多计数题可以考虑补集转化,比如要你求刚好为x,可以尝试求出>=x或<=x再减重
  • 高斯消元的本质是找到向量 x ⃗ \vec x x 满足 A × x ⃗ = c ⃗ A× \vec x=\vec c A×x =c ,其中 A A A是系数矩阵, c ⃗ \vec c c 是答案向量
  • 求边的期望可以转化成求点的期望,再乘上走这条边的概率
  • E ( x ) = ∑ i ≥ 0 P ( x = i ) ∗ i = ∑ i ≥ 0 P ( x ≥ i ) E(x)=\sum_{i\geq 0}P(x=i)*i=\sum_{i\geq 0}P(x\geq i) E(x)=i0P(x=i)i=i0P(xi)
  • 如果贡献形如“所有方案的k次方和”,出现增量不太好维护。用第二类斯特林数把k次拆开变成组合数的形式,这样就变成了组合数的和,转移本质上是范德尔蒙恒等式(GDOI2018D2T2)

  • 容斥、反演、变换是一家
  • 插值大法好
  • 差分大法好
  • 组合意义大法好
  • 当数据范围不像线性/一个log复杂度,什么思路都没有,考虑网络流

黑科技

  • 可删除堆,思想是不对堆实时更新,而是在询问的时候检验是否被打上删除标记。
struct Heap {
	priority_queue <int, vector<int>, greater<int> > Heap, Delt;
	void push(int x) {Heap.push(x); }
	void delt(int x) {Delt.push(x); }
	int query() {
		while (!Delt.empty() && Heap.top() == Delt.top()) {
			Heap.pop();
			Delt.pop();
		}
		if (Heap.empty()) return MAXV;
		else return Heap.top();
	}
};
  • Long Long相乘取模
LL mult( LL A, LL B, LL Mo )
{
    LL temp = ( ( LL ) ( ( db ) A*B/Mo+1e-6 ) * Mo );
    return A*B - temp;
}
  • 线性求1~n关于模mo的逆元
inv[i]=(mo-mo/i)*inv[mo%i]%mo;

finger tree

  • 两条路径在树上的交(from yangle71)
int depmax(int x, int y){return dep[x] > dep[y] ? x : y;}
int pathsection(int a, int b, int c, int d, int &e, int &f)
{
    int u = lca(a, b), v = lca(c, d);
    if(dep[u] > dep[v]) swap(a, c), swap(b, d), swap(u, v);
    if(lca(u, v) != u) return 0;
     
    e = depmax(lca(a, c), lca(a, d));
    f = depmax(lca(b, c), lca(b, d));
    if(max(dep[e], dep[f]) < dep[v]) return 0;
    e = depmax(e, v), f = depmax(f, v);
    return 1;
}
  • 编译命令,Dev-c++放工具-编译选项-编译时加入以下命令
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值