B. 金牌
优先填空,再整块补。
|
|
G. 乐观向上
异或和的性质
$$ f(x)=\begin{cases} x, & x\%4=0 \\ 1, & x\%4=1 \\ x+1, & x\%4=2 \\ 0, & x\%4=3 \end{cases} $$所以如果 $n%4=0 || n=1$ 此时无法构造。
交换 0 和 1,的位置,之后每 4 个交换一次即可。
|
|
A. 两星级竞赛
啥调题,谁知道卡题点在 QA 里。
暴力模拟即可, $s_i=s_j$ 时,要让当前评分总和小的排前面。
|
|
I. 左移
找到串上所有的连续段,每段贡献为长度除二,如果有偶数长度的段,可以减少一个贡献。
|
|
E. 学而时习之
由题意可知,答案是三段的 GCD($a_1…a_{l-1},a_l…a_r,a_{r+1}…a_n$),前后两段可以通过预处理得到,关键在于找到合适的中间段,即操作段。
st 表优化暴力版:
$st_{i,j}$ 表示从 i 开始,长度为 $2^j$ 的片段的 gcd 值。
|
|
L. 漫步野径
$f(x,y)=x+y$,如果有 i 条额外的路在通往 $(x,y)$ 的路上,则 $f(x,y)=x+y-i$。
所以先算出没有额外小径时总的值,再计算每条额外小径能优化的值。
首先按 yi 升序排列,xi 降序排列,保证从上到下遍历,每次的斜线都能在 LIS 中找到对应的位置。
用树状数组来维护最大 LIS 长度。
具体过程:
假设左上角为 (0,0), 右下角为 (p,q)。
我们从上到下遍历路径,并且同一行左侧的路径的区域一定能覆盖到右侧的路径的区域。
每一条路径,首先减去他能覆盖到的所有区域,再加上已经被覆盖过,无法多重贡献的区域。
LIS 通过树状数组来实现。
用 lst 数组来储存 LIS 值对应的横坐标。
树状数组中储存的是所有横坐标小于等于 x 的斜线端点中,能够形成的最长上升子序列,即能用上几个端点来减少贡献。
然后用 lst 找到这个 LIS 对应的最新的 x 坐标,加上多减的值。
|
|
M. 意大利美食
一眼丁真,直接放弃了
关键一句:等价于找一条过两顶点的弦,使得圆严格落在弦的同侧且到弦的距离 ≥ $r$,并在这条弦与多边形边界围成的那一块区域里取面积最大者。
-
弦合法 + 双指针
-
把顶点序列「摊平」成长度 $2n$ 的循环数组(首尾再补一个顶点,便于计算面积),这样任何跨越 $[i,,j]$($j$ 可跑到 $i+n$)的连续段都对应多边形上的一块“扇形”。
-
枚举左端点 $i$,用指针 $j$ 往右推,维持条件:
- 圆心在弦 $\overline{P_iP_j}$ 的左侧(叉积 $\text{cross}(P_i,P_j,C)>0$);
- 弦到圆心的距离 $\ge r$。 这保证了圆整颗都在弦外侧 → 弦与多边形分出的左边那块一定无菠萝。
-
-
快速求这块区域面积
-
预处理前缀数组
$$ A_{i,j}= \bigl(\text{sum}[j]-\text{sum}[i] + P_j\times P_i \bigr)/2 $$sum[k] = Σ_{t<k} (P_t×P_{t+1})(即累积叉积),可 O(1) 求出任意连续段 $i\sim j$ 围出的多边形面积:这里乘积是有符号的;因为顶点按逆时针给出,所以取绝对值或直接比较即可。
-
-
双指针保证每个顶点只前进一次 → 总 $O(n)$。
|
|
J. 冲向黄金城
改进 dijkstra, dis 储存两个值 {第 i 张车票, 这一张车票走了 j 米},松弛的时候,如果该边和当前车票公司一致,且加上距离后不超过车票的距离,直接转移。否则向后转移,替换新的车票状态。
| 名称 | 类型 & 维度 | 下标/键含义 | 存放的具体值 | 作用 |
|---|---|---|---|---|
e |
vector<vector<array<ll,3>>> e(n+1); |
e[u]:城市 u 的邻接表 array<ll,3>{v,c,w} |
对于每条铁路 (u,v,c,w):• v —— 相邻城市编号• c —— 铁路所属公司编号• w —— 铁路长度 |
无向图邻接表。遍历边时能直接拿到“下一城‑公司‑长度”三个字段 |
tk |
vector<pair<ll,ll>> tk(k+1); |
tk[i] = {a_i, b_i} |
旅客第 i 张车票的信息: • a_i —— 这张票允许乘坐的公司编号• b_i —— 该票一次最多可累积的总里程 |
保留所有车票的顺序与参数,Dijkstra 拓展状态时要用 |
pos |
vector<vector<int>> pos(m+1); |
pos[c]:公司 c 出现在哪些票序号上 |
依次 push 每一张属于该公司的票下标 i | 把“公司 c → 票的先后位置”映射出来,后续二分定位“下一张可用票” |
rmq |
vector<vector<vector<int>>> rmq(m+1, vector<vector<int>>(21)); |
第一维 c:公司编号第二维 j:稀疏表层级 (≥0)第三维 idx:pos[c][idx] 对应的票 |
rmq[c][0][idx] = b_i —— 公司 c 的第 idx 张票的最大里程更高层 j 里存预处理后的区间最大值 |
以公司为单位建 稀疏表 (Sparse Table),支持 get(c,l,r) O(1) 查询“公司 c 在票区间 [l,r] 里的 b_i 最大值” |
vis |
vector<ll> vis(n+1); |
vis[u] == 1/0 |
城市 u 是否已被 Dijkstra 弹出确定过最优状态 | 保证每个城市只处理一次 |
dist |
vector<pair<ll,ll>> dist(n+1,{1e18,1e18}); |
dist[u] = {ticket_id, used_len} |
抵达城市 u 的当前 最小票号 ticket_id 及在该票里已走的累计里程 used_len |
Dijkstra 的比较键:始终优先保证“更靠前的票号”,其次里程更小 |
λ get |
— | 参数 (c,l,r) |
返回 pos[c] 区间 [l,r] 里最大的 b_i |
稀疏表的 O(1) 取区间最大 |
λ bin_find |
— | 参数 (L,c,x) |
在公司 c 的票里,找 最早 且 票号 ≥ L 且 b_i ≥ x 的票编号;若不存在返回 ‑1 | 快速定位“还能继续坐公司 c 并且里程够用”的下一张票 |
整体思路小结
先按城市存图
e。按票顺序把
(a_i,b_i)填进tk;并为每个公司记录出现位置pos[c],同时把对应的b_i放进rmq[c][0]。对每个公司独立做 Sparse Table 预处理 (
rmq[c][j]),让“区间最大 b_i”查询变成 O(1)。Dijkstra 状态
{当前票 id, 在票内已花里程, 当前城市};扩展时:
- 如果还能在 当前票 上继续走公司
a_id的边且里程不超,就直接用;- 否则用
bin_find找 下一张 里程足够的同公司票,再出发。
vis标记出队;dist保存“到某城的最优(票,里程)”。最终
vis[i]为 1 的城市,就是用完全部 k 张票后可达城市,按题目要求打印。
|
|