重庆 暑假 Day 5-8

Day 5

模拟赛,1.5h 做完 A。看其它题 0.5h,做 B。

B细节有点多,好难调,很好想但是写了1h到11点了还没做出来

不是哥们太神奇了,我瞎调整了几个边界+1-1的参数没想到就过了样例1,这么多变量随便搞错一个都没了。

不是题读错了,子序列看成字串了。。浪费1.5h。下次不要边打题边写总结了。。

时间不多了,发现 D 的部分分挺好写的赶紧写,没修改和单点修。结果又没写完单点修。没修改也挂了因为没开longlong。最后是忘了判断修改的值等于原来的值时的阴间情况。

B

赛后听懂了,先考虑 \(O(n^3)\),枚举 \(l,r\),枚举中间点 \(mid\),中间点前全为 0,后为 1,答案就做一下前缀和差分拆一下,再对所有的 mid 答案取 max。

考虑优化,枚举 \(r\),左端点 l 对应的区间的最大值单调不降,这里我们只考虑区间内差分拆完会变的重要的贡献,单调栈维护这个,注意一下边界就好(\(l-1\leq mid\leq r\))。

D

P12401 [COI 2025] 玻利维亚 / Bolivija

哎对数据结构的技巧掌握实在太少。考虑每相对的两对柱子 \((\min(x,y),\max(x,y)]\),答案区间 \((A,B]\) 不能与这段区间相交。所以可以拿线段树维护区间加,对于一长段 \(=0\) 的段答案贡献加 \(\frac{len(len+1)}{2}\),转移的话就和前两天做的一道题很像。

但是有区间 \(+1,-1\) 维护 \(=0\) 的段很难,考虑维护线段树该点内 \(=\min\) 的段的贡献,这样左右儿子合并时就判断一下哪边更小或者一样小合并即可,求答案也判断一下 \(\min=0\) 再输出对应答案。

CF1454F Array Partition

枚举第一个 x,y 定义为 x+y,满足 max(1,x)=min(x+1,y) 的 y 位置是一个区间段,满足 max(1,x)=max(y+1,n) 的 y 位置也是一个区间段,这两个区间都可以二分。

P8945 Inferno

贪心+双指针+单调队列

P12013 [Ynoi April Fool's Round 2025] 牢夸

不愧是愚人节题目。所有长度 \(>1\) 的最大平均值区间只能是长度 \(2,3\),因为所有更大的都一定能再拆成更优。

可以考虑开两棵树分别记录 \(i\) 为长为 \(2,3\) 的区间的右端点的数值和。

写代码的时候发现修改操作的边界比较复杂(WA 了一发在这),可以不用考虑具体每个位置加几次,只在 \([l,r],[l+1,r+1],[l+2,r+2]\) 这三个区间加一次就可以正好算准。

P5278 算术天才⑨与等差数列

哈希秒了。\(x\to B^x\),取个模,公差为 k,最小值为 m 的等差数列的集合就是 \(B^m,B^{m+k},B^{m+2k}\dots\),这是等比数列,等比数列求和就行了。

注意特判 \(k=0(q=1)\),会 WA 然后因为强制在线导致 RE/TLE。

P4098 [HEOI2013] ALO

zx 讲过,先找左边最近两个比 \(a_i\) 大的位置,右边也是,\(a_i\) 为次大值且尽量最大的区间有左右两个,可持久化 trie 维护。

Day 6

P13957 [ICPC 2023 Nanjing R] 背包

贪心不会啊。先将所有物品按照价格排序,枚举 \(1\sim i\) 做背包,\(i+1\sim n\) 取价值最大的 k 个。

证明:假设我们知道最后的可以得到的宝石的集合,那我们发现,将价格最大的 k 个免费拿走肯定不会比其它任何方案更劣(这里的优劣是指能否达到这样的买的宝石的方案,因为我们已经确定买哪些宝石,判断能否买得起只跟价格有关,所以把价格大的拿掉肯定更有可能)。

正着很难考虑到这种取法,但是我们从确定一些信息的角度去推断就有思路了。

P3226 [HNOI2012] 集合选数

状压的美。

关键的一步在题意的转化。对于 \(1\) 这样不被 \(2\)\(3\) 整除的数,我们做一个矩阵,这个数作为左上角起点,使得同一行上的数右边是左边的 \(2\) 倍,同一列上下一个数是上一个数的 \(3\) 倍,这样题目就变成了选一些数使得它们在矩阵上不相邻。这样我们就可以对一维做状压 dp。但是这样矩阵不满,我们对于每一个不被 \(2\)\(3\) 整除的数都类似建一个矩阵,方案乘起来即可。

别用 c++ log(x) 精度误差极大,写循环

P14347 [JOISC 2019] 灯 / Lamps

先要注意到各个操作序列位置和顺序之间的关系。

  • 所有覆盖操作不相交,显然(你可能会想先全部覆盖 0 再某些覆盖 1 会很优,但是任意的多次覆盖操作可以被翻转替代,所以本质是相同的,所以这里不统计也是 ok 的)
  • 我们可以做到所有的翻转都放在覆盖之上,显然

到这一步怎么想到 dp 呢?由于现在操作区间的关系已经明确了,我们可以直接记录当前位置做了哪些操作,与下一位置不同的操作就相当于 \(+1\) 答案贡献。

dp 代码好像挺好写的啊,第一篇题解在写什么?

状压成 6 种后写两个函数分别判一下这种操作可不可以,以及相邻两种操作相对的差距

好像拆成 2 维 3*2 会更好写,写复杂了。仅供参考

const int N=1e6+10;
int n; string S,T;
int dp[N][6];
int to(int x,int y) {
    return ((x/3)!=(y/3)&&(y/3)!=0)+(x%3!=y%3&&(y%3!=0));
}
bool ck(int a,int b,int j) {
    if(j==0) return a==b;
    if(j==1) return b==0;
    if(j==2) return b==1;
    if(j==3) return a!=b;
    if(j==4) return b==1;
    if(j==5) return b==0;
}
int Solve() {
    cin>>n>>S>>T; S='_'+S; T='_'+T;
    dp[0][0]=0; rep(i,1,5) dp[0][i]=1e9;
    rep(i,1,n) {
        rep(j,0,5) {
            dp[i][j]=1e9;
            if(ck(S[i]-'0',T[i]-'0',j)) {
                rep(k,0,5) {
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+to(k,j));
                }
            }
        }
    }
    int ans=1e9;
    rep(j,0,5) ans=min(ans,dp[n][j]);
    cout<<ans;
    return 0;
}

P4678 [FJWC2018] 全排列

好难得几乎是唯一我自己做出来的题。可以考虑到枚举每一个 \((l,r)\) 有多少个 \((P_1,P_2)\) 做出贡献。可以考虑先做 \(dp\)\(dp_{i,j}\) 表示长度为 \(i\) 的排列逆序对为 \(j\) 的方案数,那么我们枚举 \((l,r)\) 它会有的 \((P_1,P_2)\) 的贡献就是 \(\sum_{j\leq E} dp_{r-l+1,j}\ (C_n^{r-l+1} (n-(r-l+1))!)^2\),看着很长实则可以分开来看:第一个 \(dp\) 的和表示 \([l,r]\) 区间内逆序对数量 \(\leq E\) 值的相对顺序的可能方案,对于每个顺序的方案都有 \(C^{r-l+1}_n\) 的选数方案,那么剩下的数顺序就可以乱选,是个阶乘;发现 \(P_2\) 的方案数和 \(P_1\) 的统计完全是一样的,以为如果这两个序列的两段相似那么两端的逆序对数也相同,组合数和阶乘是一样的。

卡空间,注意细节,少开一个 \(dp\) 数组只留下前缀和数组。

AT_dp_j Sushi

我说白了,这 dp 题单质量真的高好吧,思维难度平均比数据结构上个档次,这能是绿?

可以想到状态只维护 \(a_i=1/2/3\)\(i\) 的数量。

为什么 dp 要从 0 0 0 倒推呢?可能是因为转移的值取决于上一步的状态,这样才可以推式子转移。

对这一类式子里有自己的 dp 值的式子理解经常不深刻。。这一类题跟我来重庆前做的很多期望 dp 题是同一类。P4550 收集邮票 等等

题解:设 \(dp_{i,j,k}\) 表示分别当前\(i,j,k\) 个盘子寿司数量为 \(1,2,3\),就有 \(\frac{n-i-j-k}{n}\) 的概率选到没有寿司的盘子,从 \(dp_{i,j,k}\) 转移;\(\frac{i}{n}\) 概率选到一个寿司的盘子,从 \(dp_{i-1,j,k}\) 转移……以此类推。注意枚举顺序,\(k,j,i\) 的顺序枚举 dp。

CF115E Linear Kingdom Races

一开始有点被带偏了往 m 上 dp,后面看题解,dp i 表示 i 之前的最大值,线段树优化就行了。

CF2091G Gleb and Boating

发现性质若 \(s>k^2\) 则答案为 \(k\)\(k-2\)。显然,因为可以走到除以 \(k-2\) 为任意余数的位置,所以只考虑 \(s<k^2\) 情况。发现 bitset 暴力跑是能过的。

CF1442D Sum

比较独特的题。先从题目条件入手,将题意简化为选若干前缀,使得长度总和为 \(k\),元素总和值最大。发现递增性质的规律,即最多存在一个序列选的前缀不满也不空,其它全部尽量选满。考虑若存在两个这样的前缀,则减短一个增长另一个一定更优。

考虑 dp,满的序列可以简化成背包,枚举不满的那个位置,直接前后缀 dp 优化复杂度不够优秀。

经典的 trick 线段树分治。dp 序列很好维护新的值不好维护删除和合并。设当前分治到了区间 \([l,r]\) 表示已知除了这个区间外的 dp 值,那么先将 \([mid+1,r]\) 全加入 dp 然后递归 \([l,mid]\),左区间返回后将 dp 值还原回加入右区间前的情况,然后再类似地递归右区即可。

P4067 [SDOI2016] 储能表

数位 dp 好题。考验你对数位 dp 编写代码的熟悉程度,边界比较复杂。

wtf 调了一晚上还真是取模问题。

我的代码和 这篇题解 是很像的。注意取任意模输一定要少用 %,在需要反复使用的语句多使用判断 \(x\geq p,x:=x-p\) 这样的取模方法

考虑将答案拆成 \(\sum i\oplus j[i\oplus j>k]\)\(\sum[i\oplus j>k]\),答案就是总和减去个数乘 \(k\),这个就是我们 dp 求的答案。状压 dp 的状态枚举当前走到的值是否 \(i=n,j=m,i\oplus j=k\),前两个项像普通状压一样枚举,当当前 \(i\oplus j=k\) 但下一位 \(i\oplus j<k\) 就不继续搜索。到达末位后返回 \(sum=0,cnt=1\)

CF2204G Grid Path

好题,真的难。矩阵快速幂优化 dp。https://www.luogu.com.cn/article/2noh8kvg

可以转化成一层一层往下走,每层走一个连续段,每相邻两层必须有相交,求方案数。可以想到记录每层连续段 \(f_{l,r}\) 然后逐层根据相交转移。可以优化,设 \(s_i=\sum_{l\leq r\leq i}f_{l,r},t_i=\sum_{i\leq l\leq r}f_{l,r}\),则有 \(f_{l,r}=s_m-s_{l-1}-t_{r+1}\)

到了这一步我们就可以推式子只保留 \(s,t\) 的转移式子,可以使用矩阵优化。注意到 \(t_i=s_{m-i+1}\) 可以再优化一维。题目里要求 \(l_1=0\) 我们可以考虑倒推从 \(n\) 行开始,这样转移 \(n-1\) 次后 \(t_{1}-t_{2}=s_m-s_{m-1}\) 就是答案。

实现上的细节是很多的。我在矩阵的构建浪费 20min 就是因为没有判数组越界。由于我们可以在任意位置结束,也就是我们 dp 时要考虑从任意位置开始的贡献,用矩阵的 \(0\) 行存一个 \(1\) 做常量,注意最后只乘一次的初始矩阵的 \(0,0\) 也要是 \(1\)

abc469_e(abc比赛

二分答案

abc469_f

还是有点思维含量的。考虑降序枚举 \(d\),对所有 \(d\) 的倍数的 \(a_i\) 加入同一个并查集,这样最早达成全部合并的 \(d\) 就是答案。

Day 7

数学 令我痛苦

CF2123G Modular Sorting

把所有 m 因数对应的答案序列求出来,每次修改也更新这 \(\sqrt m\) 个序列

CF1780E Josuke and Complete Graph

整除分块入门题。https://www.luogu.com.cn/article/4qhu5x50

CF1188B Count Pairs

有点唐的推式子

AT_arc122_e [ARC122E] Increasing LCMs

好题。

https://www.luogu.com.cn/article/80r0yd7p

https://chat.deepseek.com/a/chat/s/6e7b76ee-401b-4588-9e4c-e3809bdcc03a

\(A_i\) 为答案末尾则需要满足 \(\gcd(A_i,\text{lcm}_{j\neq i}A_j)<A_i\),转换为 \(\text{lcm}(\gcd_{j\neq i}(A_i,A_j))<A_i\),这一步转换避免 \(lcm\) 过大不好储存。

既然已知答案作为末尾的条件,可以考虑倒序求答案序列。

做法:设当前 \(A\)剩余未选的元素集合\(S\),我们每次从 \(S\) 中取出任意一个满足以上条件的值作为答案,插入到答案序列的开头。

为什么这样贪心是对的呢?我们发现在不断取出 \(S\) 中元素的过程中,\(S\) 中满足条件的元素集合会单调不减,这个性质是显然的,因为每一个其它的数都是限制,取出元素限制就会减少。

那么也就是说,如果我们当前没有把一个合法的值放入答案序列,那么它不会在之后的某个时刻变为不合法,也就是说自从这个值合法的时刻开始,之后的任意时刻再将他取出都是可行的。这也能就说明,当有多个同时合法的元素时,任意选择一定是可以使答案可行的。

如果在某一步的贪心没有选到合法的值那么就无解,原因已经解释。

posted @ 2026-08-04 14:20  2020luke  阅读(8)  评论(0)    收藏  举报