前言
洒落君臣契,飞腾战伐名。(杜甫《公安县怀古》)
NOIP 前的一个月。
这浸满热血的虔信,真的会化作墓碑吗?
或许明日我们不再是战友,但人生终将有无数个此时。
本文省略以下定义:
#define F(z, u, v) for(int z = (u), des##z = (v); z <= des##z; ++z)
struct Bnd { int f, s; Bnd(int f = 0, int s = 0): f(f), s(s){}}
struct Tup { int f, s, t; Tup(int f = 0, int s = 0, int t = 0): f(f), s(s), t(t){}}
template <typename T> bool chkmax(T& a, T b) { return a < b ? a = b, 1 : 0; }
本文所有源码由命题者提供,格式已调整,并加了注释。
乱入
填一下暑假清北血糖的坑。
复习 维护区间取模、单点修改、区间和。
所以今年暑假我才会写线段树,我太弱了… 记录和的同时记录一个最大值,如果最大值小于模数就跳过即可。
Garden 给定点集 K K K,在矩阵 C \bold C C 上找两点 A , B A,B A,B 使 ∑ i ∈ S C [ i ] \sum\limits_{i\in S} \bold C[i] i∈S∑C[i] 最大,其中 S = { i : i = A + j or i = B + j , j ∈ K } S = \{i: i=A+j\text{ or }i=B+j, j\in K\} S={i:i=A+j or i=B+j,j∈K},点按照矢量运算。
棘手的问题在于重复。事实上根据抽屉原理,每个点只需选 ∣ K ∣ 2 + 1 |K|^2 + 1 ∣K∣2+1 个,就会有一个不重复的。因此每个点最大的 ∣ K ∣ 2 + 1 |K|^2 + 1 ∣K∣2+1 个即可。
D1
养花 静态区间询问模以某数后的最大值。
分块。 预处理所有除数的结果,块外暴力,块内查表。
F(i, 1, bn) { memset(lst, 0, sizeof lst);
F(j, (i - 1) * bs, std::min(i * bs, n)) lst[a[j]] = a[j];
F(j, 1, MAXQ) chkmax(lst[j], lst[j - 1]); // lst[j] 为 j 前最大值
F(j, 1, n) for(int k = 0; k <= MAXQ; k += j)
chkmax(ans[i][j], lst[std::min(k + j - 1, MAXQ)] - k); }
// 取所有 [ik, (i + 1)k) 内最大值
折射 平面上有若干定点,过之作折线,使纵坐标递增且横坐标摆幅减小,求方案数。
前缀和优化。 纵向转移需要 O ( n 3 ) \text O (n^3) O(n3),故横向转移。 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 代表节点 i i i 为顶端,向左/右的方案数。加入一新节点时其在最右,故必在首位或次位。
F(i, 1, n) { dp[i][0] = dp[i][1] = 1;
for(int j = i - 1; j >= 1; j--)
if(p[j].y > p[i].y) (dp[j][1] += dp[i][0]) %= MOD;
else (dp[i][0] += dp[j][1]) %= MOD;
ans = MOD - n; F(i, 1, n) ans = ((ans + dp[i][0]) % MOD + dp[i][1]) % MOD;
画作 在 01 矩阵上每次可以为一个四连块涂色,求从白色画出给定图形的最小步数。
搜索。 最优方案总能等价成一种修改范围逐步缩小的方案。因此,我们可搜索末态的所有点,它所需的涂色次数为最远的黑块加 1(「最远」是经过的四连块最多),尔后取最小值即可。
int bfs(int x, int y) {
static const int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, 1, 0, -1 }; // 一步之遥
std::deque<pii> q; memset(dis, -1, sizeof dis);
dis[x][y] = 0; q.push_back(Bnd(x, y));
int re = 0; while(!q.empty()) {
int cx = q.front().f, cy = q.front().s; q.pop_front();
if(g[cx][cy] == '1') chkmax(re, dis[cx][cy]);
for(int i = 0; i < 4; ++i) {
int nx = cx + dx[i], ny = cy + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && dis[nx][ny] == -1)
if(g[nx][ny] == g[cx][cy])
dis[nx][ny] = dis[cx][cy], q.push_front(Bnd(nx, ny));
else dis[nx][ny] = dis[cx][cy] + 1, q.push_back (Bnd(nx, ny)); }}
return re; }
// 主函数内:
ans = INF; F(i, 1, n) F(j, 1, m) chkmin(ans, bfs(i, j));
printf("%d\n", ans + 1);