随笔分类 - 算法
摘要:嘴巴上把这道题切了,但是写代码的时候好多细节都需要注意. 1. 大概可以猜到能表示出的数字比多,但是这一步要用 BFS+hash 才行,因为用 DP 求解的话会有好多无用状态. 2. 做动态规划的时候如果对与状态有限制条件的话比较好写的方法是由合法状态去转移下一步,而不是枚举当前状态去找上一步的状态
阅读全文
摘要:新学了一下决策单调性. 对于这道题,我们可以先考虑 $j<i$ 的情况. 然后我们发现随着 $i$ 变大,$i$ 的决策点不可能减小(因为根号函数的增长速率越来越小,所以一旦被赶超上是不可能追回来的) 然后有两种处理方式:单调队列+二分 or 整体二分. 前者细节较多,后者更好写一些. code:
阅读全文
摘要:这道题太 tm 卡内存了. 不知道这样做意义何在,是在考察选手卡常能力吗 ? 思路没啥说的,整个棋盘的形态我们是知道的. 那么显然从小到大把数往棋盘里填,然后我们每次不可以选的是一个左下角和右上角区域,暴力覆盖就行. 覆盖的时候要判一下什么时候 break,来保证每个地方只被覆盖依次. code:
阅读全文
摘要:当相邻字母不相同的时候做法显然,相同的时候将相同区间提取出来,然后按照不同做就行. code: #include <bits/stdc++.h> #define ll long long #define N 1000006 #define setIO(s) freopen(s".in","r",st
阅读全文
摘要:这个可以爆搜,如果搜出来环的话就一定不合法. 这个时间复杂度是 $O(n^4)$ 的. 但是我们发现,如果向右侧搜的话右侧许多方块会把很多状态都提前搜出来了. 所以我们可以从左向右枚举,搜左面.从右向左枚举,搜右面. 这样时间复杂度就是 $O(n^3)$ 的了. code: #include <bi
阅读全文
摘要:这道题拿左偏树做的话时间复杂度好像是 $O(n \log n)$ 的,拿 $Splay$ 的话就是 $O(n \log^2 n)$ 的. $Splay$ 真恶心,真心不好写,要不是可以练习代码能力的话我才不用 $Splay$. code: #include <bits/stdc++.h> #defi
阅读全文
摘要:显然,我们可以将每个东西的 $a,b$ 属性转换成二维坐标系中的点. 那么我们每次查询的时候查的是一个右下角矩阵. 没有被套的数量等于矩阵内总数量减去矩阵内可以套其他物品的数量. 我们考虑按照 $a$ 从大到小依次处理. 那么对于 $(x,y)$ 来说,显然匹配一个 $(x',y')$ 满足 $y'
阅读全文
摘要:简单记忆化搜索. 显然,数字的形态是类似阶梯下降的,状态数不会太多,记忆化爆搜就行. code: #include <bits/stdc++.h> #define N 12 #define mod 1000000007 #define base 12 #define ll long long #de
阅读全文
摘要:显然,如果不出现重复数字的话直接贪心填就是正确的. 然而,当出现重复数字时这个贪心就错了. 将这个问题抽象成树是显然的. 我们先将所有数从大到小排. 对于大小为 $size[i]$ 的 $i$ 来说,肯定选当前能选的第 $size[i]$ 大的. (设为 $x$) 那么,选择完 $x$ 后,显然 $
阅读全文
摘要:这种出现异或的题一般来说都是进行二进制拆位,然后按位考虑的. 我们考虑第 $i$ 位是否为 1. 不妨模 $2^{i+1}$,排除前面的影响. 那么一对 $a[k]+b[k]$ 中第 $i$ 位为 1 的条件是: 1. 由后面进位,得 $i$ 位为 1. 2. 两个位置都是 1,但是进位后还是 1.
阅读全文
摘要:好神仙的数据结构题呀! code: #include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <algorithm> #define BL 250 #define N 100006 #define
阅读全文
摘要:如果 $k$ 值确定的话,我们直接来一个 $O(n)$ 的贪心就行. 那么我们就将 $k$ 分为大于 $B$ 和小于 $B$ 两部分处理. 对于小于 $B$ 的部分,暴力处理,复杂度为 $O(nB)$. 对于大于 $B$ 的部分,取值分别为 $[0,\frac{n}{B}]$ 且依次递减. 那么我们
阅读全文
摘要:这道题的数据范围中有两个需要注意到的点: 1. 边都是由编号小的点连向编号大的点. 2. 总点数只有 $10^5$ 个. 所以我们可以考虑采取根号分治的做法: 对于点数大于 $\sqrt n$ 的部分,直接跑一个 $O(n)$ 的 DP. 对于点数小于 $\sqrt n$ 的部分,提前预处理. 这样
阅读全文
摘要:按照挂件数量排序,然后做一个 DP 就好了. code: #include <bits/stdc++.h> #define ll long long #define N 2003 #define setIO(s) freopen(s".in","r",stdin) using namespace s
阅读全文
摘要:显然从左到右,从上到下依次处理每个格子步数是最少的. 而由于我们的顺序是固定的,每次操作等于是一个区间修改,单点查询. 利用二维差分的方式可以轻松实现. code: #include <cstdio> #include <cstring> #include <string> #include <ve
阅读全文
摘要:用 trie 搜索一下就好了. code: #include <bits/stdc++.h> #define N 10008 #define setIO(s) freopen(s".in","r",stdin) using namespace std; char S[24]; int trie[N*
阅读全文
摘要:第一次写这个题是好长时间以前了,然后没调出来. 本来以为是思路错了,结果今天看题解发现思路没错,但是好多代码细节需要注意. code: #include <cstdio> #include <vector> #include <map> #include <cstring> #include <al
阅读全文
摘要:A - Sasha and a Bit of Relax code: #include <cstdio> #include <map> #include <cstring> #include <algorithm> #define N 300006 #define ll long long #def
阅读全文
摘要:思路很巧妙啊 code: #include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define N 1000009 #define setIO(s) freopen(s".in","r",stdi
阅读全文
摘要:看到这道题第一个想法肯定是按照套路钦定一些地方不合法,然后其他地方随便选,最后来一个二项式反演. 但是我们发现这个 DP 状态很难设置. 然后你发现一个非常神的性质:由于题中给的是绝对值,所以说一个位置要是不合法的话,只有两种数值的可能(+k和-k) 然后把位置 $i$ 和值 $i+/-k$ 相连,
阅读全文

浙公网安备 33010602011771号