2026 寒假大学习

Day 1

P11086 [ROI 2019] 机器人高尔夫 (Day 2)

首先考虑朴素 \(\Omicron(nm)\)
\((i,j),(i+1,j),(i+2,j),(i,j+1),(i,j+2),(i+1,j+1)\) 都为空
\(g_{i,j} = \min(\max(g_{i+2,j},g_{i+1,j+1}),\max(g_{i,j+2},g_{i+1,j+1}))\)

等价于 \(g_{i,j} = \max(\min(g_{i+2,j},g_{i,j+2}),g_{i+1,j+1})\)

发现仍然不好做,令 \(f_{i,j}\) 为后手先的答案,进一步展开寻找性质

\(g_{i+2,j} = \min(f_{i+3,j},f_{i+2,j+1})\)
\(g_{i,j+2} = \min(f_{i,j+3},f_{i+1,j+2})\)
\(g_{i+1,j} = \min(f_{i+2,j+1},f_{i+1,j+2})\)

\(\min(g_{i+2,j},g_{i,j+2}) = \min(f_{i+3,j},f_{i,j+3},g_{i+1,j+1})\)

所以 \(\min(g_{i+2,j},g_{i,j+2}) \le g_{i+1,j+1}\)

\(g_{i,j} = g_{i+1,j+1}\)

那么关键点 \(\Omicron(k)\) 个,把这些点的 \(g\) 求出来后,再计数一下非关键点的贡献即可

#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a; i<=b; ++i)
#define pii pair<int,int>
#define fr first
#define sc second
#define pb push_back
typedef long long ll;
const int N = 2e5+10; const ll Mod = 998244353;
int n,m,k;
struct ROLE{
	int x,y,v;
} rl[N];
map<pii,ll> dp[2],vis;
map<int,ll> lst,nxt[2];
vector<pii> keyp;
ll ans;
bool inmap(int x,int y){
	return x>=1&&x<=n&&y>=1&&y<=m;
}
int main(){
	cin >> n >> m >> k;
	F(i,1,k) cin>>rl[i].x>>rl[i].y>>rl[i].v;
	F(i,1,k){
		int x=rl[i].x, y=rl[i].y, v=rl[i].v;
		dp[0][{x,y}] = dp[1][{x,y}] = v;
		keyp.pb({x,y}), keyp.pb({x-1,y}), keyp.pb({x,y-1}), keyp.pb({x-2,y}), keyp.pb({x,y-2}), keyp.pb({x-1,y-1});
	}
	sort(keyp.begin(),keyp.end(),greater<pii>());
	for (auto elm:keyp){
		int x = elm.fr, y = elm.sc;
		if (!inmap(x,y) || vis.count({x,y})) continue;
		if (!dp[0].count({x,y})){
			F(o,0,1){
				int a = nxt[o^1][(x+1)-y], b = nxt[o^1][x-(y+1)];
				dp[o][{x,y}] = (o?max(a,b):min(a,b));
			}
		}
		F(o,0,1) nxt[o][x-y] = dp[o][{x,y}];
		vis[{x,y}] = 1;
	}
	sort(keyp.begin(),keyp.end());
	for (auto elm:keyp){
		int x = elm.fr, y = elm.sc;
		if (!inmap(x,y)) continue;
		ans = (ans + dp[0][{x,y}]*(min(x,y)-lst[x-y])%Mod + Mod)%Mod;
		lst[x-y] = min(x,y);
	}
	cout << ans;
	return 0;
}

P3647 [APIO2014] 连珠线

由题目中构造方式,我们可以把两条相邻蓝线分为一组,那么所有的蓝线组都包括三个点,且中间的点都不相同

于是可以树形 DP,设 \(dp_{u,0/1}\) 表示以 \(u\) 为根的子树内,是否存在单条未成组的蓝线的答案,考虑转移

首先考虑没有横跨 \(u\) 的蓝线组,则

\[dp_{u,0} = \sum_{v\in son(u)} \max\{dp_{v,0},dp_{v,1}+w(u,v)\} \]

\[dp_{u,1} = \sum_{v\in son(u)} \max\{dp_{v,0},dp_{v,1}+w(u,v)\} + \max_{v\in son(u)} \{dp_{v,0}+w(u,v) - \max\{dp_{v,0},dp_{v,1}+w(u,v)\}\} \]

若存在横跨 \(u\) 的蓝线组,直接 dp 会 WA,给出 hack: 深度为 3 的满二叉树

这是构造过程中可能使得我们有一个森林,这个森林的所有根不能用蓝线连接,也就是上面所说的“横跨 \(u\) 的蓝线组”,所以在构造过程中一定有一个所有蓝线所连的点的“总根”,dp,时间复杂度 \(\Omicron (n^2)\)

容易发现这个可以换根 dp 优化到 \(\Omicron(n)\)

Day 2

CF1667C Half Queen Cover

答案上界可以定为 \(n-1\),现在重点考虑答案下界

设当前放了 \(k\) 个不同行列的半皇后,那么会还剩下 \((n-k)^2\) 个格子,把这些格子拼起来可以得到一个 \((n-k) \times (n-k)\) 的正方形,显然需要斜线覆盖这些格子,那么仅当这些格子形成一个 \((n-k) \time (n-k)\) 的正方形时,斜线数最少

\(k \ge 2 \times (n-k)-1\),即 \(k \ge \lceil \frac{2n-1}{3}\rceil\)

\(n = 3m+2\),则 \(k = 2m+1\),我们把斜线画过去,那么怎么构造都可以满足,其中其中方式是两条 \(k = -\frac{1}{2}\)

\(n = 3m\),则 \(k = 2m\),按照上面的方法,只用 \(2m-1\) 个半皇后,然后发现有一个角上的格子覆盖不到,直接放一个半皇后即可

\(n = 3m+1\),则 \(k = 2m+1\),直接用 \(n+1\) 的构造

AT_arc172_d [ARC172D] Distance Ranking

观察到 \(n\) 极小,而点的坐标可以到很大,难以直接做

考虑等于时怎么做,那么显然令 \(p_{i,j} = [i = j]\)

然后我们微调一下,使得满足小于关系,设 \(p_{i,j}\) 的微扰为 \(c_{i,j}\),远小于 \(1\)

\(dis(P_{a_i},P_{b_i})\) 变成一个很长的式子。但是观察到二次项过小,可以忽略,于是式子变成

\[\sqrt{2 + 2(p_{a_i,b_i} - p_{a_i,b_i} - p_{b_i,b_i} + p_{b_i,a_i})}\]

\(p_{a_i,a_i}\)\(p_{a_j,b_j}\) 可以不用微扰,直接设成 \(10^8\),而 \(p_{a_i,b_i}\)\(p_{b_i,a_i}\) 其中一个设为 \(0\),另一个可以按 \(i\) 正序或倒序来排名

Day 3

折半警报器

我们希望在线解决如下形式的问题:

给定长度为 \(n\) 的数组和 \(q\) 次操作,每次操作如下:

  1. 给数组一个位置加 \(v\)
  2. 给定不超过 \(k\) 个位置,要求在数组这些位置的总和超过 \(v\) 的时候输出该操作的编号。

一般 \(k\) 非常小

利用鸽巢原理,我们如果一个报警器可能到达 \(v\),那么其监视的屋子至少有一个到达 \(\large\frac{v}{k}\),于是我们利用优先队列等数据结构在每个点上存储一些监视器信息,到达阈值时检查一下

但是这样复杂度仍然不对,我们到达阈值检查完后,可以更新阈值,让 \(v\) 减去现在的总和 \(s\),那么这样阈值至少变成 \(\large\frac{k-1}{k}\),时间复杂度就是 \(O(n\log n \log V)\)

Day 4

LCT 相关题目

1

Task

维护一个 \(n\) 个节点的无向图

1.加边
2.删边
3.查询x和y是否连通

允许离线

Sol

1.线段树分治
2.LCT 维护边的删除时间的最大生成树

2

Task

\(n\) 个点,任意两点 \((u,v)\) 有条边,边权为 \(gcd(u,v)\),求最大生成树的边权和。

Sol

发现可以转化为全部是 \(u,v\) 为倍数关系的边,于是枚举每个数的约数,LCT 维护最大生成树

3

Task

\(n\) 个点 \(m\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数,强制在线

Sol

先用 LCT 预处理一下,依次加入每一条边

当前加入第 \(i\) 条边,如果这个边加入之后成环了,就弹出这个环上面编号最小的边 \(x\),并且记录下 \(b_i = x\),默认 \(b_i = 0\)
之后就是查询区间中 \(b\) 值小于 \(l\) 的数个数
因为如果 \(b\) 值小于 \(l\),那这个边与 \([l,r]\) 内边不成环,所以连通块数量 \(-1\)。否则没有贡献

posted @ 2026-02-05 15:44  huangyuze  阅读(2)  评论(0)    收藏  举报