2026年4月解题报告

七夕祭

和均分纸牌很像,可以称作 “环状均分纸牌” 。

行和列都各自跑一遍类似于均分纸牌的代码,以行为例子:
先判断 \(T/M\) 是否为整数。
接着记录每一列的感兴趣的个数 \(c_i\)
类似于均分纸牌,然后记录 \(a_i=c_i-T/M\)
最后答案即为 \(\sum_{i=1}^{M} |s_i-s_k| ,s_i= \sum_{j=1}^{i}a_j\)
前头的字符串判一下即可,还有,\(k=(n+1)/2\) 就行了。

[国家集训队] 小 Z 的袜子

前段是推式子:
$\frac{ans_i}{(r_i-l_i+1)(r_i-l_i)/2} $。

推出来以后打一个莫队,最后输出时要记得特判和约分。

大爷的字符串题

阅读理解+莫队板子题。

这么一 堆东西:

  • 如果 \(S\) 为空,你 rp 减 \(1\)
  • 如果 \(S\) 中有一个元素不小于 \(x\),则你 rp 减 \(1\),清空 \(S\)
  • 之后将 \(x\) 插入 \(S\)

我们稍加分析就会发现,求的其实就是区间众数出现的次数

得出这个结论后,一个莫队就行了,adddel 如下:

void add(int x){
    s[cnt[a[x]]]--;
    s[++cnt[a[x]]]++;
    ANS=max(ANS,cnt[a[x]]);
}
void del(int x){
   s[cnt[a[x]]]--; 
   if(cnt[a[x]]==ANS&&!s[cnt[a[x]]])ANS--; 
   s[--cnt[a[x]]]++;
}

CF633H Fibonacci-ish II

说是莫队,但暴力可过。

俗话说得好:

暴力的 \(nq\) 是可过的

以及

\(n^2\) 过百万,暴力碾标算

于是,我们就 充分发扬人类智慧 写一个暴力,再加一点点优化就过了。

[AHOI2013] 作业

玄学的时间复杂度qwq。

莫队加 BIT ,两问分别处理,

[HAOI2008] 糖果传递

水蓝 。纯推式子。

和均分纸牌有相似之处,先算 ave=sumA/n ,接着设 \(c_i=ave-a_i\), 于是,\(i\) 号人给 \(i-1\) 号人的糖果个数 \(x_i=x_{i-1}-c_i\)

不难发现,最终答案 \(\sum_{i=1}^{n}|x_i|=|x_1|+|x_1-c_1|+|x_1-c_2|+...+|x_1-c_n|\)

那么问题就一目了然了啊,借助中位数就过了。

小 Z 的 AK 计划

想清楚了其实不难。

我们记录一个机房的总时间 \(tot_i=x_i+t_i\) ,塞进一个 node a[100010] ,从小到大排序。
我们接着从 \(1\)\(n\) 遍历,每遇到一个机房就把它加入答案。

但是,我们不得不面对一个问题:这样很明显会有很多重合的,从而导致 WA 。

于是我们记录一个 \(head\) ,用来去重。
每次记录 \(head=a[i].x\) ,可以基本达到去重目的。
如下:

for(int i=1;i<=n;i++){
   if(sum+a[i].tot-head>m)break;
   sum+=a[i].tot-head;
   head=a[i].x;
   ans++;
}

card

01 背包 DP 。

我们分析题目,会发现,想要使用一个集合 S 内的所有符卡,必须满足:

\(\sum_{i\in S}l_i≤n\)

于是乎,这道题就转化为了一道求 \(\sum l_i≤n\)\(\sum d_i\) 的最大值。

这个问题 01 背包就行了。

128. 编辑器

开对顶栈。

本身代码很简单,Luogu 黄题,但是 AcWing 的数据还是 毒瘤 强度太大了。

要注意的点其实不多,主要是两个:

  • 必须判空栈,否则空栈 pop 会崩溃。
  • 可能有负数。

当然,光标位置手打 pos 也不太好,最好利用 a.size()

应该没人像我一样没用 a.size() 然后神秘地WA了吧。。。

[蓝桥杯青少年组省赛 2023] 最大的矩形纸片

单调栈好题。

我们依次遍历每一个高度,利用单调栈的思想:

  • 若当前高度高于栈顶,压进去。
  • 否则不断弹栈顶,直至前高度高于栈顶,并同时累计答案,最后把当前元素压进去。

这种思路可以用于解决很多序列上的最值问题

油滴扩展

简述一下题意:
\(n\) 个圆,每个圆依次不断变大,不论碰到什么就会停止变大,问你调整变大顺序以后长方形盒子剩余的最小空间即盒子 面积减去这几个圆最大能占据的空间

我们可以称此题是一道 选取方案求最值问题 ,遇到这种问题,我们比较常见的思路一般是使用 DFS(深度优先搜索) 来解决。

那么,比较显然的是,我们需要根据前面所确定的油滴的坐标和半径来确定当前的油滴的半径。
对于每一个油滴,我们用一个 cal(x) 函数来计算半径,我们在函数中不断去取此油滴与边框和其他油滴距离的 min 即可。

这道题和普通的 选取方案求最值问题 还是有所不同的,这道题其实是可以代表选取方案求最值问题中的一类问题的,我们可以将其称为:选取方案求几何最值问题 ,这一类问题的一个通用解法是:DFS+ 套用几何公式的剪枝 ,整体来说难度并不算太大,但是仍然需要我们了解大量几何公式,如 $dis_{(x_1,y_1) \to(x_2,y_2)}=\sqrt[]{(x_1-x_2)2+(y_1-y_2)2} \(、\)a2+b2=c^2$ 等。

[NOIP 2009 提高组] 靶形数独

题意很简单:
有一个九宫格数独,填数的规则与正常数独一致,每一个点有一个对应的分数如下,求每个点上面的数字乘以对应的分数只和的最大值。

int score[10][10]={
   {0,0,0,0,0,0,0,0,0,0},
   {0,6,6,6,6,6,6,6,6,6},
   {0,6,7,7,7,7,7,7,7,6},
   {0,6,7,8,8,8,8,8,7,6},
   {0,6,7,8,9,9,9,8,7,6},
   {0,6,7,8,9,10,9,8,7,6},
   {0,6,7,8,9,9,9,8,7,6},
   {0,6,7,8,8,8,8,8,7,6},
   {0,6,7,7,7,7,7,7,7,6},
   {0,6,6,6,6,6,6,6,6,6}
};

首先,我们考虑直接暴搜,很明显会 TLE ,于是我们考虑剪枝:

由于数据比较水,我们其实仅仅需要一个小剪枝即可:从 \(0\) 的数量小的开始搜。
整体的难度是在代码实现这里,但其实也还好,多多检查即可。

但是为什么我考试时没有 AC 呢?仔细想来还是代码能力的问题,代码还是打得少了。

如果不算这个靶型的分数,这道题其实也可以算是 填数独类题目 的一个标程。

[NOI1999] 生日蛋糕

这道题其实就是前面说的 选取方案求几何最值问题 ,思路差不多,也是 DFS+ 套用几何公式的剪枝

我们用 minsminv 记录第 \(i\) 层的表面积和体积的 \({理论最小值}\) ,再利用这个 理论最小 来剪枝。

首先,我们来讨论第一个最简单的剪枝:

看图可以发现,我们不需要每一次都记录底面积然后做一些神秘的运算,只需要在最后 s+=i*i 即可。

接着,我们来看一下另外几个可行性剪枝:

  • (1)如果理论最小加现在面积已经大于了目前最优值就 return
  • (2)如果当前体积大于给定体积就 return 。;
  • (3)如果当前剩余体积组出来的半径不变的圆柱侧面积加现在面积大于目前最优值就 return

剪完枝后,我们继续往下递归,但是往下继续递归这件事本身就是很易错的。

for(int i=r-1;i>=now;--i){
    if(now==m)s=i*i;
    minh=min(h-1,(n-minv[now-1]-v)/(i*i));
    for(int j=minh;j>=now;--j)dfs(now-1,i,j,s+2*i*j,v+i*i*j);
}

易错点其实是 minh 的取值:minh=min(h-1,...); ,由于 minh 它代表的是下一层高度的取值上限,于是我们可能就会误把 minh 算成 max(h-1,...),所以以后在赛场上命名变量名时还是最好加上一个注释比较好。

[CERC 1995] 小木棍

剪枝好题。

我们想考虑 优化搜索顺序 :从大到小排序来尝试拼接。
为什么呢?因为越长的木棍越不灵活。
什么意思呢,我们可以感性理解一下:
我们要凑长度 \(d\) ,我们如果先拿短的去凑,凑到一半突然堵上来一根很长的,直接就前功尽弃了;所以我们就选择从大到小尝试。

我们还可以 排除等效的冗余操作 :由于 先 A 后 B 和先 B 后 A 没有差别,于是我们可以只考虑前面一种操作。

接着又考虑一些 可行性剪枝

  • 由于要凑出的长度 \(d\) 为总长度的约数。所以如果不是约数直接 return 即可。
  • 相同长度的木棍不要搜索多次,用当前的得不出结果,下一支同样长度的还是得不到
  • 判断当前长度是不是大于每段应该的长度,如果大于则没必要往下递归
  • if(all-times+1<res-now) 判断剩下的是否还足以拼成需要的段数

4.21

[COCI 2006/2007 #1] Slikar

有一个地图,上面有:

  • * :释放洪水的地方,洪水会一点一点扩散,不可以走洪水。
  • S :起点。
  • D :终点。
  • X :不可以走的地方。
  • . :可以走的地方。

求安全到达终点所需的最短时间。如果不可能,输出KAKTUS

我们会发现,如果我们不考虑洪水,这就是一道很简单的 BFS

那么,思路就比较显然了:
我们先考虑让问题复杂的洪水,计算每一个格子最早什么时候会被洪水覆盖,这一步你可以选择很多算法,我在这里考虑 BFS ;接着我们直接搜,如果到一个格子时已经被洪水覆盖,return 即可 。

[NOIP 2010 提高组] 引水入城

在有解的情况下,第一行每个格子放水流到最后一行的位置一定是一个区间。
假设放水的格子流到的格子如下:

又有一个放水的如下:

那么,显然,我们会有:

所以,在有解的情况下,第一行每个格子放水流到最后一行的位置一定是同一个区间。
于是,可以使用 BFS 求出第一行每个格子流到的区间,然后 区间覆盖贪心 就好了。

#1554. [2020普转提七连测day3] 神奇位运算

看到题目刚开始还是会比较懵的,即使简化了题意。

但是不论如何,先考虑位运算的性质:

\(1 ~and ~1 = 1\)
\(1 ~and ~0 = 0\)
\(0 ~and ~0 = 0\)

\(1 ~or ~1 = 1\)
\(1 ~or ~0 = 1\)
\(0 ~or ~0 = 0\)

\(1 \oplus 1 = 0\)
\(1 \oplus 0 = 1\)
\(0 \oplus 0 = 1\)

于是我们会发现对于每一种运算,只要我们进行 \(11,10,00\) 这三次操作即可确定符号。
于是对于每一位,我们必须要有两个 \(1\)

但是,赛时的 \(40\) 就是这样轻率的分析导致的。

于是,我们继续看看,就会发现,显然 \(00\) 是没有大用的,有前两个足矣,所以,我们就只要满足每一位必须要有两个 \(1\) 和一个 \(0\)

统计 \(k\) 的代码如下:

int F_0=0;
int F_1=0;
for(int i=1;i<=m;i++){
  int flag_0=0;
  int flag_1=0;
  for(int j=1;j<=n;j++){
    if(a[j][i]=='1')flag_1++;
    else flag_0++;
  }
  F_0=max(F_0,1-flag_0);
  F_1=max(F_1,2-flag_1);
}
cout<<max(F_1,F_0)<<endl;

但是,虽然思路看着比较简单,但我在赛时也并没有一下子想到。

为什么呢?原因可能是自己对于位运算掌握的不是很好,对于各种位运算是干什么的还是有点混乱。

所以,即使是很久很久以前学的东西还是要经常复习,一些老旧的玩意儿在现在啥题都有的赛场上还是挺有用的。

#1556. [2020普转提七连测day3] 终焉之排列

既然是比赛,那么只要有分,暴力也不是不行,但是数据过于水,结果 \(A\) 了,跑的和标程速度也差不多。

所以,以后在赛场上,不会的题就打暴力骗分,骗出来一个 \(AC\) 也说不定。

#1553. [2020普转提七连测day3] aria的礼物

读题以后,我们解决这道题的关键是一个不那么显然的性质:\(a_i=a_{n-k+i}=a_{2(n-k)+i}\) ,成一个序列。

有了这样一个性质乃至于是约束,我们就可以设计出一种类似贪心的思路:

先定义:
\(vis_{i,j} :\)\(i\) 个序列中 \(j\) 号字母出现的次数;
\(num_i :\)\(i\) 个序列中出现最多次字母出现的次数。

于是我们利用 \(vis\) 统计 \(num\) ,再将每一个序列全部换成出现最多次字母。

for(int i=1;i<n-k;i++)sum+=(n-i)/(n-k)+1-num[i];
sum+=k/(n-k)+1-num[0];

[USACO24JAN] Potion Farming S

详细版见 date 3.28 ,此为简化版。

本题是传统题。观察到本题是以树为背景的,而且注意到经过 \(u\) 的路径数,等价于 \(u\) 这个子树内叶子节点的个数,所以本题选择使用树上 DP ,对于 \(u\) 这一棵子树,动态规划它这一棵子树里最多可以拿到多少药水,就可以得到 \(100\) 分。

posted @ 2026-05-12 20:48  Tri_Function  阅读(1)  评论(0)    收藏  举报