思路与好题记录与小技巧
记录好题,值得看看或再做一遍:
p1306 SDOI2008,P1377仪仗队
BZOJ1067降雨量
想看的东西:
https://ruanx.pw/post/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3.html
https://zhuanlan.zhihu.com/p/20085048
http://www.cnblogs.com/zzqsblog/p/5851393.html
http://hzwer.com/8053.html
http://www.matrix67.com/blog/archives/276
http://blog.csdn.net/PoPoQQQ/article/details/53166326
http://blog.csdn.net/tgop_knight/article/details/44539555
http://rapiz.cf/2017/link-cut-tree/
http://www.cnblogs.com/mlystdcall/p/6232324.html
http://blog.csdn.net/chty2018/article/details/53432272
http://vfleaking.blog.163.com/blog/static/1748076342013112523651955/
http://blog.csdn.net/u011466175/article/details/38712967
http://blog.csdn.net/pi9nc/article/details/9615359
平方和公式
https://zhuanlan.zhihu.com/p/26020672
https://zhuanlan.zhihu.com/p/25984772
http://www.cnblogs.com/zzqsblog/p/6700133.html
看见如果有平方的柿子尝试把平方拆开,这样就会出现一个对应位置相乘的项(-2*ai*bi)和常数项(ai^2+bi^2),这样很可能就卷积了
字符串循环同构匹配只需要一个串循环就行了,因为如果a串循环的话b串可以通过额外循环和a串循环相同步数来使相对位置相同
所以循环同构匹配只需要一个串循环就行了
组合数可以用杨辉三角递推 组合数可以用杨辉三角递推 组合数可以用杨辉三角递推 这是NOIP2016的教训QAQ
涉及到整除或质数是考虑一下全场膜某个数 涉及到整除或质数是考虑一下全场膜某个数 涉及到整除或质数是考虑一下全场膜某个数 这个也是NOIP2016的教训QAQQQQ
字符串没有思路的时候可以试试蛤习,就算A不掉应该也有很实惠的暴力分数
尝试反向可以是突破点,比如反向搜索,反向枚举,甚至反向DP
果然反向是突破点吗,只有删除+离线是不是就可以考虑反成插入处理了?
减法原理也是突破点
二分也是,转换问题很关键
取反两次等于没变,这个在很多和取反有一点点关系的地方都很可能用到,比如某次cf激光反射,用这个关系可以简化问题然后直接exgcd
fill大多时候比memset更好,因为fill可以指定填充的长度,容易卡过更多的数据
vector可以存想n*m<=100000这样的数据又能很方便地调用
数位DP:f[i][j]表示前i位膜T等于j的方案数,酱紫可以处理想求一个长度为n的大整数使得它(不)是a1,a2,a3……的倍数,T=a1*a2*a3……
网络流如果边数无法承受可以考虑借助前面的点/边导向需要的边,详情可以看BZOJ1930
如果求后缀数组的字符串很长(比如1e6),加上:"if(rk1[sa[i]]==rk1[sa[i-1]] || rk2[sa[i]]==rk2[sa[i-1]]) flg=false; if(flg) break;"似乎可以让代码快很多
数据量很大的时候在可能进行无用操作的地方加上剪枝可以大幅度提高效率(比如上面),但是这个数据量是否足够大到可以消耗额外时间剪枝的问题……真是玄……
(结构体名){结构体中的变量1,结构体中的变量2}可以表示一个临时的结构体
只有两个未知数的时候(二维坐标比较多)可以尝试想exgcd,比如某次cf激光反射
经实测,bfs的时候搞一个spfa中的visited来表示这个元素是否在队中,如果在队中就不进队,这个优化效果还是不错的
背包似乎可以重复利用?祥利见关灯问题
背包如果不限制必须装满的话f[容量]就是最大值,因为不必从0,开始装
多个数向一个数靠拢,每个数字变化相同大小消耗相同,则最优解是中位数,这是定理
尽量把函数写到struct里面可以在一定程度上减少这种傻逼错误的出现……(这个bug我调了7h
一种树套树不好搞可以尝试把里外树调换或换一种树
动态删除或插入可以把插入/删除顺序看成一维,然后树结构/cdq分治搞
动态开开点可以先开一个数组,再用一个队列或栈来记录空余的节点,每次开点就从队列或栈中取,删除点就放到队列或栈中
动态开点的线段树可以当平衡树(每个节点的左右边界表示这个节点的子树节点的权值范围)
轻重链不止可以用来剖,更多用来忽略一条重链上无用的节点,比如某点到根不同的颜色,就使相邻且颜色相同的点在一条重链上,就可以通过重链快速跳跃(这个好像就是动态树?
这个是容斥dfs的一般形式:
if(x==n+1) return y*z;
return dfs(x+1,选,z)+dfs(x+1,不选,z*-1);
形似上面的dfs(或者其他形式的dfs应该也可以),如果所有状态种数不大但是dfs复杂度很大,可以使用记忆化搜索,dfs的复杂度大似乎是有很多多余的东西,这些东西是怎么多出来的不用知道,只要记忆化去掉即可
我终于知道喂猫满装背包要把初始值设成-OO辣,因为这样子就可以保证重量是一个接一个挨着一直到v,因为如果不是挨着的,f[j-weight[i]]就没有东西,值就是-oo,value[i]加上去没有什么影响
扩展欧几里得求的是ax+by=gcd(a,b),如果要求ax+by=c的时候,还是直接把a和b丢进去算,求出来的是ax+by=gcd(a,b)的解,在把整个式子(不过我们只要x,y)转化成ax+by=c
可以通过判断flag[color[e[j].y]]=i来判断i个颜色有没有被周围的任何一个节点染色,这样就不用memset了
区间覆盖DP:if(i>=left[j] && i<=right[j]) f[i]=min(f[i],f[left[j]-1]+1)
可以通过实验特殊情况来判断可能性,比如NOIP2010引水入城就可以假设第一行全建站了,来判断最后一行是否可以完全覆盖以及如果不能完全覆盖有多少个格子覆盖不到
遇到多维点要建图的时候,可以用一个计数,给每个点都标上号,用一个多维数组记录标号,连边的时候就很方便
把x和y的变化量分别设成{1,-1,0,0},{0,0,1,-1},这样直接用k^1就可以快速取到反向边
scanf("%abd");表示输出一个b位的int,如果位数不够前面补a,这个在输出万进制高精度的时候比较好用
使用a&1来快速判断奇偶
有时候可以用DP预处理一些很实用的东西,比如NOIP2008双栈排序用一个很简单的前缀和DP来优化判断
邻接矩阵虽然很慢,但在节点数不多且要求按照序号递增遍历的话邻接矩阵是个不错的选择
使用类型+空格+*+变量名来将数组作为变参传进函数
高精度除一个小于10000的数这个是我自己脑出来的OvO:
直接用万进制从高位开始除,把除剩下的数也就是这一位膜除的数的结果乘10000加到下一位上去,继续往下除
结果的长度是被除数的长度-(被除数最高位<除数)
如果DP怎么都想不出来,或者会有其它东西影响状态转移,可以尝试多维,将影响的东西另开一维
如果要计算ΣΣai*aj,可以先计算出c=Σai,然后在计算Σai*(ci-ai),可以省一维复杂度
如果乘数过大连longlong都会炸掉,可以使用二进制分配乘:
1 LL f(LL x,LL y) 2 { 3 LL tmp=0; 4 while(y) 5 { 6 if(y&1) 7 tmp=(tmp+x)%p; 8 y=y>>1; 9 x=(x<<1)%p; 10 } 11 return tmp; 12 }
原理就是将其中一个乘数分解成二进制,比如5 * 17就是5 * (16 + 1),5 * 23 就是 5 * (16 + 4 + 2 + 1),逐步膜就不会炸longlong
求割集bfs,遍历到的和没遍历到的之间的连边就是割边,因为在求最大流的时候反向边流量增加了所以下面这条边不会被算进去
求字典序最小的割集只能枚举边删除然后最大流验证,如果删边后的最大流变小了,这个边就是割集中的一个,删掉的边就不还原了,然后更新最小的最大流,然而我怎么搞都不行,好晕qaq
↑所以说暴力出奇迹,想不出复杂度优美的算法就暴力硬肛
dfs如果没法记忆化,可以尝试改变参数的表达方式,或者换另一种可行的搜索方式,也可以找互补的搜索方式,一个更加具体的例子是状态不表示为搜索的序列,而是序列的两端点,这样就可以忽略下标直接剪枝,在添加两端点的时候直接更新花费
涉及到取模或整除的DP时可以考虑枚举取模后的数做一维状态
syzoj上看到的黑科技:解n皇后问题
我觉得i+j和i-j+n应该是向右斜和向左斜分别映射到最上边和最左边(吧
用壮鸭低劈处理铺砖问题的时候dfs枚举的满足这一行的状态s1需要的上一行的状态s2,最后将满足s1的s2对应的方案加进s1里,所以s2可以存在空格(这也算无后效性吧
依旧是转化问题,来自传纸条,比如求从一个点到另一个点然后再回来的路径,要求去的和回来的路径不能相交,这个时候没必要计算回来的路径,直接记录两条从一个点到另一个点的两条不相交的路径即可