如何构建思维网络
前言
发现现在越来越靠经验行事了,如果遇到思维题目或者很简单的 DP,也有可能是线段树变体,都想不出来
举个例子,比如有些题目如果要求最小值,其实是可以二分的,但是二分的方向可能与众不同
所以这个位置主要要放一些杂七杂八的东西,等会读者看见了就知道了
经典 问题/Trick
被夺舍了
这里放一些 trick和经典问题
下面是 Trick
下面是经典问题
- 1.欧拉回路
Trick
处理 abs,max 函数
首先说一下 abs 的处理方式
遇见 \(|x-y|\) 的一般情况可能是在一维坐标系,二维坐标系的情况基本上就可以直接扫描线做了
所以虽然处理一维坐标系简单,但是我们依旧需要转化成二维坐标系,因为二维坐标系有我们需要的性质
这种情况我们可以将 \(|x-y|\) 变成 \(\max{(x-y,y-x)}\) 然后在进行下一步的操作
如何处理 \(\max\),单个的 \(\max\) 如果存在于不等式中,很容易发现可以拆成两个式子,如果是很多个数字的 \(\max\) 可以当成二分答案,当然也可以将其转化为绝对值做。
如果一个 \(\max\) 被转化为了坐标系上的一个点,就可以直接扫描线扫过去做了。
一些特殊的函数问题
很容易发现特殊的函数很多都没有办法处理,比如 CF2045E 中所提到的:
其中 \(m1=\max\limits_{i=l}^r a_i,m2=\max\limits_{i=l}^r b_i\)。
这种情况很难处理,上面我们提到了
两个东西,发现这里的 \(\min\) 函数居然没有最后一个 \([x=y]*x\) 了,这就可以简化很多东西。
现在剩下的 \(m1+m2-[m1=\max(m1,m2)]*m1-[m2=\max(m1,m2)]*m2\) 可以通过单调栈求出每一个 \(a_i\) 作为 \(m1\) 和 \(m2\) 的结果,\(m1,m2\) 也可以同样的求出
经典问题
欧拉回路问题
inline void dfs_find(int x){
while(st[x]<imp[x].size()){
if(vis[imp[x][st[x]].first]){st[x]++;continue;}
vis[imp[x][st[x]].first]=1;
dfs_find(imp[x][st[x]].second);
st[x]++;
}
ans.push(x);
}
欧拉回路或者欧拉路径问题很简单
上面的代码要背或者理解,每一次走到一个相邻的点然后删除这个边,没边回溯,思考为什么这是对的
发现我们一定有解的情况下如果没边了回溯就相当于在走这个点前插入了回溯的点,所以一定是能找到解的,\(O(m)\)。
附易错点
- 1.快速幂的时候求 \(x^y\) 可以用 \((x \mod M)^y\) 或者 \((x \mod M)^{(y\mod (M-1))}\),记住一定是 \(\mod (M-1)\)
- 2.快速幂一定要开 \(ll\),包括不限于 \(res,x,y,mod\)
- 3.在比较卡常的题目(比如卡 \(n\log_2n\) 的题目,并且正解的常数较大)的情况下,记得保存每一版代码,并且每一次更改后都要保证代码正确性(不要嫌麻烦)
- 4.想到题目了就立刻去写,下次不写就是正赛不写,给我去死
总体问题
思考问题本质

浙公网安备 33010602011771号